1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-16 14:00:40 +00:00

Refactored 2D shader and lighting system

-Removed normal/specular properties from nodes
-Create CanvasTexture, which can contain normal/specular channels
-Refactored, optimized and simplified 2D shaders
-Use atlas for light textures.
-Use a shadow atlas for shadow textures.
-Use both items aboves to make light rendering stateless (faster).
-Reorganized uniform sets for more efficiency.
This commit is contained in:
reduz
2020-10-24 12:15:43 -03:00
parent b67ccf1a6f
commit 84d734da0e
48 changed files with 1330 additions and 1471 deletions

View File

@@ -26,7 +26,7 @@ layout(location = 3) out vec2 pixel_size_interp;
#endif
#ifdef USE_MATERIAL_UNIFORMS
layout(set = 1, binding = 1, std140) uniform MaterialUniforms{
layout(set = 1, binding = 0, std140) uniform MaterialUniforms{
/* clang-format off */
MATERIAL_UNIFORMS
/* clang-format on */
@@ -226,7 +226,7 @@ layout(location = 3) in vec2 pixel_size_interp;
layout(location = 0) out vec4 frag_color;
#ifdef USE_MATERIAL_UNIFORMS
layout(set = 1, binding = 1, std140) uniform MaterialUniforms{
layout(set = 1, binding = 0, std140) uniform MaterialUniforms{
/* clang-format off */
MATERIAL_UNIFORMS
/* clang-format on */
@@ -408,7 +408,7 @@ FRAGMENT_SHADER_CODE
color *= canvas_data.canvas_modulation;
#ifdef USE_LIGHTING
for (uint i = 0; i < MAX_LIGHT_TEXTURES; i++) {
for (uint i = 0; i < MAX_LIGHTS_PER_ITEM; i++) {
if (i >= light_count) {
break;
}
@@ -430,7 +430,8 @@ FRAGMENT_SHADER_CODE
light_base &= 0xFF;
vec2 tex_uv = (vec4(vertex, 0.0, 1.0) * mat4(light_array.data[light_base].texture_matrix[0], light_array.data[light_base].texture_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
vec4 light_color = texture(sampler2D(light_textures[i], texture_sampler), tex_uv);
vec2 tex_uv_atlas = tex_uv * light_array.data[light_base].atlas_rect.zw + light_array.data[light_base].atlas_rect.xy;
vec4 light_color = textureLod(sampler2D(atlas_texture, texture_sampler), tex_uv_atlas, 0.0);
vec4 light_base_color = light_array.data[light_base].color;
#ifdef LIGHT_SHADER_CODE_USED
@@ -502,47 +503,53 @@ FRAGMENT_SHADER_CODE
}
}
distance *= light_array.data[light_base].shadow_zfar_inv;
//float distance = length(shadow_pos);
float shadow;
uint shadow_mode = light_array.data[light_base].flags & LIGHT_FLAGS_FILTER_MASK;
vec4 shadow_uv = vec4(tex_ofs, 0.0, distance, 1.0);
vec4 shadow_uv = vec4(tex_ofs, light_array.data[light_base].shadow_y_ofs, distance, 1.0);
if (shadow_mode == LIGHT_FLAGS_SHADOW_NEAREST) {
shadow = textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x;
shadow = textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x;
} else if (shadow_mode == LIGHT_FLAGS_SHADOW_PCF5) {
vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0);
shadow = 0.0;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 2.0).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 2.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 2.0, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 2.0, 0.0).x;
shadow /= 5.0;
} else { //PCF13
vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0);
shadow = 0.0;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 6.0).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 5.0).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 4.0).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 3.0).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 2.0).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 2.0).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 3.0).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 4.0).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 5.0).x;
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 6.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 6.0, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 5.0, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 4.0, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 3.0, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 2.0, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 2.0, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 3.0, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 4.0, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 5.0, 0.0).x;
shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 6.0, 0.0).x;
shadow /= 13.0;
}
vec4 shadow_color = light_array.data[light_base].shadow_color;
vec4 shadow_color = unpackUnorm4x8(light_array.data[light_base].shadow_color);
#ifdef LIGHT_SHADER_CODE_USED
shadow_color *= shadow_modulate;
#endif
shadow_color.a *= light_color.a; //respect light alpha
light_color = mix(light_color, shadow_color, shadow);
//light_color = mix(light_color, shadow_color, shadow);
}
uint blend_mode = light_array.data[light_base].flags & LIGHT_FLAGS_BLEND_MASK;

View File

@@ -8,7 +8,8 @@ layout(push_constant, binding = 0, std430) uniform Constants {
mat4 projection;
mat2x4 modelview;
vec2 direction;
vec2 pad;
float z_far;
float pad;
}
constants;
@@ -25,9 +26,18 @@ void main() {
#version 450
layout(push_constant, binding = 0, std430) uniform Constants {
mat4 projection;
mat2x4 modelview;
vec2 direction;
float z_far;
float pad;
}
constants;
layout(location = 0) in highp float depth;
layout(location = 0) out highp float distance_buf;
void main() {
distance_buf = depth;
distance_buf = depth / constants.z_far;
}

View File

@@ -1,3 +1,6 @@
#define MAX_LIGHTS_PER_ITEM 16
#define M_PI 3.14159265359
#define FLAGS_INSTANCING_STRIDE_MASK 0xF
@@ -22,13 +25,7 @@
#define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 26)
#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27)
// In vulkan, sets should always be ordered using the following logic:
// Lower Sets: Sets that change format and layout less often
// Higher sets: Sets that change format and layout very often
// This is because changing a set for another with a different layout or format,
// invalidates all the upper ones.
/* SET0: Draw Primitive */
// Push Constant
layout(push_constant, binding = 0, std430) uniform DrawData {
vec2 world_x;
@@ -53,26 +50,17 @@ layout(push_constant, binding = 0, std430) uniform DrawData {
}
draw_data;
// In vulkan, sets should always be ordered using the following logic:
// Lower Sets: Sets that change format and layout less often
// Higher sets: Sets that change format and layout very often
// This is because changing a set for another with a different layout or format,
// invalidates all the upper ones (as likely internal base offset changes)
/* SET0: Globals */
// The values passed per draw primitives are cached within it
layout(set = 0, binding = 1) uniform texture2D color_texture;
layout(set = 0, binding = 2) uniform texture2D normal_texture;
layout(set = 0, binding = 3) uniform texture2D specular_texture;
layout(set = 0, binding = 4) uniform sampler texture_sampler;
layout(set = 0, binding = 5) uniform textureBuffer instancing_buffer;
/* SET1: Is reserved for the material */
#ifdef USE_MATERIAL_SAMPLERS
layout(set = 1, binding = 0) uniform sampler material_samplers[12];
#endif
/* SET2: Canvas Item State (including lighting) */
layout(set = 2, binding = 0, std140) uniform CanvasData {
layout(set = 0, binding = 1, std140) uniform CanvasData {
mat4 canvas_transform;
mat4 screen_transform;
mat4 canvas_normal_transform;
@@ -84,16 +72,6 @@ layout(set = 2, binding = 0, std140) uniform CanvasData {
}
canvas_data;
layout(set = 2, binding = 1) uniform textureBuffer skeleton_buffer;
layout(set = 2, binding = 2, std140) uniform SkeletonData {
mat4 skeleton_transform; //in world coordinates
mat4 skeleton_transform_inverse;
}
skeleton_data;
#ifdef USE_LIGHTING
#define LIGHT_FLAGS_BLEND_MASK (3 << 16)
#define LIGHT_FLAGS_BLEND_MODE_ADD (0 << 16)
#define LIGHT_FLAGS_BLEND_MODE_SUB (1 << 16)
@@ -110,37 +88,52 @@ struct Light {
mat2x4 texture_matrix; //light to texture coordinate matrix (transposed)
mat2x4 shadow_matrix; //light to shadow coordinate matrix (transposed)
vec4 color;
vec4 shadow_color;
vec2 position;
uint shadow_color; // packed
uint flags; //index to light texture
float height;
float shadow_pixel_size;
float pad0;
float pad1;
float pad2;
float height;
vec2 position;
float shadow_zfar_inv;
float shadow_y_ofs;
vec4 atlas_rect;
};
layout(set = 2, binding = 3, std140) uniform LightData {
layout(set = 0, binding = 2, std140) uniform LightData {
Light data[MAX_LIGHTS];
}
light_array;
layout(set = 2, binding = 4) uniform texture2D light_textures[MAX_LIGHT_TEXTURES];
layout(set = 2, binding = 5) uniform texture2D shadow_textures[MAX_LIGHT_TEXTURES];
layout(set = 0, binding = 3) uniform texture2D atlas_texture;
layout(set = 0, binding = 4) uniform texture2D shadow_atlas_texture;
layout(set = 2, binding = 6) uniform sampler shadow_sampler;
layout(set = 0, binding = 5) uniform sampler shadow_sampler;
#endif
layout(set = 0, binding = 6) uniform texture2D screen_texture;
layout(set = 2, binding = 7, std430) restrict readonly buffer GlobalVariableData {
layout(set = 0, binding = 7) uniform sampler material_samplers[12];
layout(set = 0, binding = 8, std430) restrict readonly buffer GlobalVariableData {
vec4 data[];
}
global_variables;
/* SET3: Render Target Data */
/* SET1: Is reserved for the material */
#ifdef SCREEN_TEXTURE_USED
//
layout(set = 3, binding = 0) uniform texture2D screen_texture;
/* SET2: Instancing and Skeleton */
#endif
layout(set = 2, binding = 0, std430) restrict readonly buffer Transforms {
vec4 data[];
}
transforms;
/* SET3: Texture */
layout(set = 3, binding = 0) uniform texture2D color_texture;
layout(set = 3, binding = 1) uniform texture2D normal_texture;
layout(set = 3, binding = 2) uniform texture2D specular_texture;
layout(set = 3, binding = 3) uniform sampler texture_sampler;