You've already forked godot
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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user