SkyShaders working

This commit is contained in:
clayjohn 2022-04-29 15:34:01 -07:00
parent 516ec892b4
commit 3bb8e6a9fe
17 changed files with 620 additions and 172 deletions

View File

@ -92,9 +92,9 @@ public:
static void make_current() { static void make_current() {
_create_func = _create_current; _create_func = _create_current;
low_end = true;
} }
virtual bool is_low_end() const { return true; }
uint64_t get_frame_number() const { return frame; } uint64_t get_frame_number() const { return frame; }
double get_frame_delta_time() const { return delta; } double get_frame_delta_time() const { return delta; }

View File

@ -238,37 +238,81 @@ void RasterizerSceneGLES3::_update_dirty_skys() {
dirty_sky_list = nullptr; dirty_sky_list = nullptr;
} }
void RasterizerSceneGLES3::_draw_sky(Sky *p_sky, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_custom_fov, float p_energy, const Basis &p_sky_orientation) { void RasterizerSceneGLES3::_draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform) {
ERR_FAIL_COND(!p_sky); GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
ERR_FAIL_COND(!p_env);
glDepthMask(GL_TRUE); Sky *sky = sky_owner.get_or_null(p_env->sky);
glEnable(GL_DEPTH_TEST); ERR_FAIL_COND(!sky);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND); GLES3::SkyMaterialData *material_data = nullptr;
RID sky_material;
RS::EnvironmentBG background = p_env->background;
if (sky) {
ERR_FAIL_COND(!sky);
sky_material = sky->material;
if (sky_material.is_valid()) {
material_data = static_cast<GLES3::SkyMaterialData *>(material_storage->material_get_data(sky_material, RS::SHADER_SKY));
if (!material_data || !material_data->shader_data->valid) {
material_data = nullptr;
}
}
if (!material_data) {
sky_material = sky_globals.default_material;
material_data = static_cast<GLES3::SkyMaterialData *>(material_storage->material_get_data(sky_material, RS::SHADER_SKY));
}
} else if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
sky_material = sky_globals.fog_material;
material_data = static_cast<GLES3::SkyMaterialData *>(material_storage->material_get_data(sky_material, RS::SHADER_SKY));
}
ERR_FAIL_COND(!material_data);
material_data->bind_uniforms();
GLES3::SkyShaderData *shader_data = material_data->shader_data;
ERR_FAIL_COND(!shader_data);
glDepthMask(GL_FALSE);
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LEQUAL);
glColorMask(1, 1, 1, 1); glDisable(GL_BLEND);
//state.sky_shader.version_bind_shader(sky_globals.default_shader, SkyShaderGLES3::MODE_BACKGROUND); //glBindBufferBase(GL_UNIFORM_BUFFER, 2, p_sky.directional light data); // Directional light data
//glBindBufferBase(GL_UNIFORM_BUFFER, 0, state.canvas_instance_data_buffers[state.current_buffer]); // Canvas data updated here
//glBindBufferBase(GL_UNIFORM_BUFFER, 1, state.canvas_instance_data_buffers[state.current_buffer]); // Global data
//glBindBufferBase(GL_UNIFORM_BUFFER, 2, state.canvas_instance_data_buffers[state.current_buffer]); // Directional light data
//glBindBufferBase(GL_UNIFORM_BUFFER, 3, state.canvas_instance_data_buffers[state.current_buffer]); // Material uniforms
// Camera // Camera
CameraMatrix camera; CameraMatrix camera;
if (p_custom_fov) { if (p_env->sky_custom_fov) {
float near_plane = p_projection.get_z_near(); float near_plane = p_projection.get_z_near();
float far_plane = p_projection.get_z_far(); float far_plane = p_projection.get_z_far();
float aspect = p_projection.get_aspect(); float aspect = p_projection.get_aspect();
camera.set_perspective(p_custom_fov, aspect, near_plane, far_plane); camera.set_perspective(p_env->sky_custom_fov, aspect, near_plane, far_plane);
} else { } else {
camera = p_projection; camera = p_projection;
} }
Basis sky_transform = p_env->sky_orientation;
sky_transform.invert();
sky_transform = p_transform.basis * sky_transform;
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_bind_shader(shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::ORIENTATION, sky_transform, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::PROJECTION, camera.matrix[2][0], camera.matrix[0][0], camera.matrix[2][1], camera.matrix[1][1], shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::POSITION, p_transform.origin, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TIME, time, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::EXPOSURE, p_env->exposure, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::TONEMAPPER, p_env->tone_mapper, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_set_uniform(SkyShaderGLES3::WHITE, p_env->white, shader_data->version, SkyShaderGLES3::MODE_BACKGROUND);
// Bind a vertex array or else OpenGL complains. We won't actually use it
glBindVertexArray(sky_globals.quad_array);
glDrawArrays(GL_TRIANGLES, 0, 3); glDrawArrays(GL_TRIANGLES, 0, 3);
//glDepthMask(GL_FALSE); // Leave off for transparent pass
glDepthFunc(GL_LESS);
} }
Ref<Image> RasterizerSceneGLES3::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) { Ref<Image> RasterizerSceneGLES3::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) {
@ -674,12 +718,14 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
Environment *env = environment_owner.get_or_null(p_environment); Environment *env = environment_owner.get_or_null(p_environment);
bool fb_cleared = false; bool fb_cleared = false;
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
/* Depth Prepass */ /* Depth Prepass */
glBindFramebuffer(GL_FRAMEBUFFER, rb->framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, rb->framebuffer);
glViewport(0, 0, rb->width, rb->height);
if (!fb_cleared) { if (!fb_cleared) {
glClearDepth(1.0f); glClearDepth(1.0f);
@ -730,7 +776,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
} }
if (draw_sky) { if (draw_sky) {
//_draw_sky(sky, render_data.cam_projection, render_data.cam_transform, env->sky_custom_fov, env->bg_energy, env->sky_orientation); _draw_sky(env, render_data.cam_projection, render_data.cam_transform);
} }
if (p_render_buffers.is_valid()) { if (p_render_buffers.is_valid()) {
@ -1014,9 +1060,9 @@ RasterizerSceneGLES3::RasterizerSceneGLES3(RasterizerStorageGLES3 *p_storage) {
String global_defines; String global_defines;
global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now global_defines += "#define MAX_GLOBAL_VARIABLES 256\n"; // TODO: this is arbitrary for now
global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_globals.max_directional_lights) + "\n"; global_defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_globals.max_directional_lights) + "\n";
state.sky_shader.initialize(global_defines); GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.initialize(global_defines);
sky_globals.shader_default_version = state.sky_shader.version_create(); sky_globals.shader_default_version = GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_create();
state.sky_shader.version_bind_shader(sky_globals.shader_default_version, SkyShaderGLES3::MODE_BACKGROUND); GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_bind_shader(sky_globals.shader_default_version, SkyShaderGLES3::MODE_BACKGROUND);
} }
{ {
@ -1038,12 +1084,76 @@ void sky() {
material_storage->material_set_shader(sky_globals.default_material, sky_globals.default_shader); material_storage->material_set_shader(sky_globals.default_material, sky_globals.default_shader);
} }
{
sky_globals.fog_shader = material_storage->shader_allocate();
material_storage->shader_initialize(sky_globals.fog_shader);
material_storage->shader_set_code(sky_globals.fog_shader, R"(
// Default clear color sky shader.
shader_type sky;
uniform vec4 clear_color;
void sky() {
COLOR = clear_color.rgb;
}
)");
sky_globals.fog_material = material_storage->material_allocate();
material_storage->material_initialize(sky_globals.fog_material);
material_storage->material_set_shader(sky_globals.fog_material, sky_globals.fog_shader);
}
{
{
//quad buffers
glGenBuffers(1, &sky_globals.quad);
glBindBuffer(GL_ARRAY_BUFFER, sky_globals.quad);
{
const float qv[16] = {
-1,
-1,
0,
0,
-1,
1,
0,
1,
1,
1,
1,
1,
1,
-1,
1,
0,
};
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16, qv, GL_STATIC_DRAW);
}
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
glGenVertexArrays(1, &sky_globals.quad_array);
glBindVertexArray(sky_globals.quad_array);
glBindBuffer(GL_ARRAY_BUFFER, sky_globals.quad);
glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, nullptr);
glEnableVertexAttribArray(RS::ARRAY_VERTEX);
glVertexAttribPointer(RS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(8));
glEnableVertexAttribArray(RS::ARRAY_TEX_UV);
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
}
}
} }
RasterizerSceneGLES3::~RasterizerSceneGLES3() { RasterizerSceneGLES3::~RasterizerSceneGLES3() {
state.sky_shader.version_free(sky_globals.shader_default_version); GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_free(sky_globals.shader_default_version);
storage->free(sky_globals.default_material); storage->free(sky_globals.default_material);
storage->free(sky_globals.default_shader); storage->free(sky_globals.default_shader);
storage->free(sky_globals.fog_material);
storage->free(sky_globals.fog_shader);
} }
#endif // GLES3_ENABLED #endif // GLES3_ENABLED

View File

@ -97,6 +97,10 @@ private:
RID shader_default_version; RID shader_default_version;
RID default_material; RID default_material;
RID default_shader; RID default_shader;
RID fog_material;
RID fog_shader;
GLuint quad = 0;
GLuint quad_array = 0;
uint32_t max_directional_lights = 4; uint32_t max_directional_lights = 4;
uint32_t roughness_layers = 8; uint32_t roughness_layers = 8;
uint32_t ggx_samples = 128; uint32_t ggx_samples = 128;
@ -319,7 +323,7 @@ protected:
Sky *dirty_list = nullptr; Sky *dirty_list = nullptr;
//State to track when radiance cubemap needs updating //State to track when radiance cubemap needs updating
//SkyMaterialData *prev_material; GLES3::SkyMaterialData *prev_material;
Vector3 prev_position = Vector3(0.0, 0.0, 0.0); Vector3 prev_position = Vector3(0.0, 0.0, 0.0);
float prev_time = 0.0f; float prev_time = 0.0f;
@ -335,17 +339,12 @@ protected:
void _invalidate_sky(Sky *p_sky); void _invalidate_sky(Sky *p_sky);
void _update_dirty_skys(); void _update_dirty_skys();
void _draw_sky(Sky *p_sky, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_custom_fov, float p_energy, const Basis &p_sky_orientation); void _draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform);
public: public:
RasterizerStorageGLES3 *storage; RasterizerStorageGLES3 *storage;
RasterizerCanvasGLES3 *canvas; RasterizerCanvasGLES3 *canvas;
// References to shaders are needed in public space so they can be accessed in RasterizerStorageGLES3
struct State {
SkyShaderGLES3 sky_shader;
} state;
GeometryInstance *geometry_instance_create(RID p_base) override; GeometryInstance *geometry_instance_create(RID p_base) override;
void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override; void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override; void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;

View File

@ -342,25 +342,13 @@ void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder,
*/ */
RS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const { RS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const {
return RS::INSTANCE_NONE; if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
/*
if (mesh_owner.owns(p_rid)) {
return RS::INSTANCE_MESH; return RS::INSTANCE_MESH;
} else if (light_owner.owns(p_rid)) {
return RS::INSTANCE_LIGHT;
} else if (multimesh_owner.owns(p_rid)) {
return RS::INSTANCE_MULTIMESH;
} else if (immediate_owner.owns(p_rid)) {
return RS::INSTANCE_IMMEDIATE;
} else if (reflection_probe_owner.owns(p_rid)) {
return RS::INSTANCE_REFLECTION_PROBE;
} else if (lightmap_capture_data_owner.owns(p_rid)) {
return RS::INSTANCE_LIGHTMAP_CAPTURE;
} else {
return RS::INSTANCE_NONE;
} }
*/ if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
return RS::INSTANCE_MULTIMESH;
}
return RS::INSTANCE_NONE;
} }
bool RasterizerStorageGLES3::free(RID p_rid) { bool RasterizerStorageGLES3::free(RID p_rid) {
@ -379,80 +367,19 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
} else if (GLES3::MaterialStorage::get_singleton()->owns_material(p_rid)) { } else if (GLES3::MaterialStorage::get_singleton()->owns_material(p_rid)) {
GLES3::MaterialStorage::get_singleton()->material_free(p_rid); GLES3::MaterialStorage::get_singleton()->material_free(p_rid);
return true; return true;
} else if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
GLES3::MeshStorage::get_singleton()->mesh_free(p_rid);
return true;
} else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
GLES3::MeshStorage::get_singleton()->multimesh_free(p_rid);
return true;
} else if (GLES3::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) {
GLES3::MeshStorage::get_singleton()->mesh_instance_free(p_rid);
return true;
} else { } else {
return false; return false;
} }
/* /*
} else if (skeleton_owner.owns(p_rid)) {
Skeleton *s = skeleton_owner.get_or_null(p_rid);
if (s->update_list.in_list()) {
skeleton_update_list.remove(&s->update_list);
}
for (Set<InstanceBaseDependency *>::Element *E = s->instances.front(); E; E = E->next()) {
E->get()->skeleton = RID();
}
skeleton_allocate(p_rid, 0, false);
if (s->tex_id) {
glDeleteTextures(1, &s->tex_id);
}
skeleton_owner.free(p_rid);
memdelete(s);
return true;
} else if (mesh_owner.owns(p_rid)) {
Mesh *mesh = mesh_owner.get_or_null(p_rid);
mesh->instance_remove_deps();
mesh_clear(p_rid);
while (mesh->multimeshes.first()) {
MultiMesh *multimesh = mesh->multimeshes.first()->self();
multimesh->mesh = RID();
multimesh->dirty_aabb = true;
mesh->multimeshes.remove(mesh->multimeshes.first());
if (!multimesh->update_list.in_list()) {
multimesh_update_list.add(&multimesh->update_list);
}
}
mesh_owner.free(p_rid);
memdelete(mesh);
return true;
} else if (multimesh_owner.owns(p_rid)) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid);
multimesh->instance_remove_deps();
if (multimesh->mesh.is_valid()) {
Mesh *mesh = mesh_owner.get_or_null(multimesh->mesh);
if (mesh) {
mesh->multimeshes.remove(&multimesh->mesh_list);
}
}
multimesh_allocate(p_rid, 0, RS::MULTIMESH_TRANSFORM_3D, RS::MULTIMESH_COLOR_NONE);
_update_dirty_multimeshes();
multimesh_owner.free(p_rid);
memdelete(multimesh);
return true;
} else if (immediate_owner.owns(p_rid)) {
Immediate *im = immediate_owner.get_or_null(p_rid);
im->instance_remove_deps();
immediate_owner.free(p_rid);
memdelete(im);
return true;
} else if (light_owner.owns(p_rid)) { } else if (light_owner.owns(p_rid)) {
Light *light = light_owner.get_or_null(p_rid); Light *light = light_owner.get_or_null(p_rid);
light->instance_remove_deps(); light->instance_remove_deps();

View File

@ -20,6 +20,15 @@ layout(location = 4) in vec2 uv_attrib;
layout(location = 10) in uvec4 bone_attrib; layout(location = 10) in uvec4 bone_attrib;
layout(location = 11) in vec4 weight_attrib; layout(location = 11) in vec4 weight_attrib;
#endif
// This needs to be outside clang-format so the ubo comment is in the right place
#ifdef MATERIAL_UNIFORMS_USED
layout(std140) uniform MaterialUniforms{ //ubo:4
#MATERIAL_UNIFORMS
};
#endif #endif
/* clang-format on */ /* clang-format on */
#include "canvas_uniforms_inc.glsl" #include "canvas_uniforms_inc.glsl"
@ -38,15 +47,6 @@ out vec2 pixel_size_interp;
#endif #endif
#ifdef MATERIAL_UNIFORMS_USED
layout(std140) uniform MaterialUniforms{
//ubo:4
#MATERIAL_UNIFORMS
};
#endif
#GLOBALS #GLOBALS
void main() { void main() {

View File

@ -26,9 +26,9 @@ out vec2 uv_interp;
void main() { void main() {
// One big triangle to cover the whole screen // One big triangle to cover the whole screen
vec2 base_arr[3] = vec2[](vec2(-1.0, -2.0), vec2(-1.0, 2.0), vec2(2.0, 2.0)); vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0));
uv_interp = base_arr[gl_VertexID]; uv_interp = base_arr[gl_VertexID];
gl_Position = vec4(uv_interp, 1.0, 1.0); gl_Position = vec4(uv_interp, 0.0, 1.0);
} }
/* clang-format off */ /* clang-format off */
@ -50,6 +50,8 @@ precision mediump int;
#endif #endif
#endif #endif
#include "tonemap_inc.glsl"
in vec2 uv_interp; in vec2 uv_interp;
/* clang-format on */ /* clang-format on */
@ -63,12 +65,7 @@ uniform sampler2D half_res; //texunit:-2
uniform sampler2D quarter_res; //texunit:-3 uniform sampler2D quarter_res; //texunit:-3
#endif #endif
layout(std140) uniform CanvasData { //ubo:0 layout(std140) uniform SceneData { //ubo:0
mat3 orientation;
vec4 projection;
vec4 position_multiplier;
float time;
float luminance_multiplier;
float pad1; float pad1;
float pad2; float pad2;
}; };
@ -88,15 +85,16 @@ layout(std140) uniform DirectionalLights { //ubo:2
} }
directional_lights; directional_lights;
/* clang-format off */
#ifdef MATERIAL_UNIFORMS_USED #ifdef MATERIAL_UNIFORMS_USED
layout(std140) uniform MaterialUniforms{ layout(std140) uniform MaterialUniforms{ //ubo:3
//ubo:3
#MATERIAL_UNIFORMS #MATERIAL_UNIFORMS
} material; };
#endif #endif
/* clang-format on */
#GLOBALS #GLOBALS
#ifdef USE_CUBEMAP_PASS #ifdef USE_CUBEMAP_PASS
@ -117,6 +115,12 @@ layout(std140) uniform MaterialUniforms{
#define AT_QUARTER_RES_PASS false #define AT_QUARTER_RES_PASS false
#endif #endif
// mat4 is a waste of space, but we don't have an easy way to set a mat3 uniform for now
uniform mat4 orientation;
uniform vec4 projection;
uniform vec3 position;
uniform float time;
layout(location = 0) out vec4 frag_color; layout(location = 0) out vec4 frag_color;
void main() { void main() {
@ -128,7 +132,7 @@ void main() {
cube_normal.z = -cube_normal.z; cube_normal.z = -cube_normal.z;
cube_normal = normalize(cube_normal); cube_normal = normalize(cube_normal);
vec2 uv = uv_interp * 0.5 + 0.5; vec2 uv = gl_FragCoord.xy; // uv_interp * 0.5 + 0.5;
vec2 panorama_coords = vec2(atan(cube_normal.x, cube_normal.z), acos(cube_normal.y)); vec2 panorama_coords = vec2(atan(cube_normal.x, cube_normal.z), acos(cube_normal.y));
@ -148,17 +152,17 @@ void main() {
vec3 inverted_cube_normal = cube_normal; vec3 inverted_cube_normal = cube_normal;
inverted_cube_normal.z *= -1.0; inverted_cube_normal.z *= -1.0;
#ifdef USES_HALF_RES_COLOR #ifdef USES_HALF_RES_COLOR
half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * luminance_multiplier; half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal);
#endif #endif
#ifdef USES_QUARTER_RES_COLOR #ifdef USES_QUARTER_RES_COLOR
quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * luminance_multiplier; quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal);
#endif #endif
#else #else
#ifdef USES_HALF_RES_COLOR #ifdef USES_HALF_RES_COLOR
half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * luminance_multiplier; half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0);
#endif #endif
#ifdef USES_QUARTER_RES_COLOR #ifdef USES_QUARTER_RES_COLOR
quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * luminance_multiplier; quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0);
#endif #endif
#endif #endif
@ -168,12 +172,19 @@ void main() {
} }
frag_color.rgb = color * position_multiplier.w / luminance_multiplier; // Tonemap before writing as we are writing to an sRGB framebuffer
frag_color.a = alpha; color *= exposure;
color = apply_tonemapping(color, white);
color = linear_to_srgb(color);
// Blending is disabled for Sky, so alpha doesn't blend #ifdef USE_BCS
// alpha is used for subsurface scattering so make sure it doesn't get applied to Sky color = apply_bcs(color, bcs);
if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) { #endif
frag_color.a = 0.0;
} #ifdef USE_COLOR_CORRECTION
color = apply_color_correction(color, color_correction);
#endif
frag_color.rgb = color;
frag_color.a = alpha;
} }

View File

@ -0,0 +1,117 @@
#ifdef USE_BCS
uniform vec3 bcs;
#endif
#ifdef USE_COLOR_CORRECTION
#ifdef USE_1D_LUT
uniform sampler2D source_color_correction; //texunit:-1
#else
uniform sampler3D source_color_correction; //texunit:-1
#endif
#endif
// These could be grouped into some form of SceneData UBO along with time, will have to test performance though
uniform int tonemapper;
uniform float exposure;
uniform float white;
vec3 apply_bcs(vec3 color, vec3 bcs) {
color = mix(vec3(0.0), color, bcs.x);
color = mix(vec3(0.5), color, bcs.y);
color = mix(vec3(dot(vec3(1.0), color) * 0.33333), color, bcs.z);
return color;
}
#ifdef USE_COLOR_CORRECTION
#ifdef USE_1D_LUT
vec3 apply_color_correction(vec3 color) {
color.r = texture(source_color_correction, vec2(color.r, 0.0f)).r;
color.g = texture(source_color_correction, vec2(color.g, 0.0f)).g;
color.b = texture(source_color_correction, vec2(color.b, 0.0f)).b;
return color;
}
#else
vec3 apply_color_correction(vec3 color) {
return textureLod(source_color_correction, color, 0.0).rgb;
}
#endif
#endif
vec3 tonemap_filmic(vec3 color, float p_white) {
// exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers
// also useful to scale the input to the range that the tonemapper is designed for (some require very high input values)
// has no effect on the curve's general shape or visual properties
const float exposure_bias = 2.0f;
const float A = 0.22f * exposure_bias * exposure_bias; // bias baked into constants for performance
const float B = 0.30f * exposure_bias;
const float C = 0.10f;
const float D = 0.20f;
const float E = 0.01f;
const float F = 0.30f;
vec3 color_tonemapped = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F;
float p_white_tonemapped = ((p_white * (A * p_white + C * B) + D * E) / (p_white * (A * p_white + B) + D * F)) - E / F;
return color_tonemapped / p_white_tonemapped;
}
// Adapted from https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
// (MIT License).
vec3 tonemap_aces(vec3 color, float p_white) {
const float exposure_bias = 1.8f;
const float A = 0.0245786f;
const float B = 0.000090537f;
const float C = 0.983729f;
const float D = 0.432951f;
const float E = 0.238081f;
// Exposure bias baked into transform to save shader instructions. Equivalent to `color *= exposure_bias`
const mat3 rgb_to_rrt = mat3(
vec3(0.59719f * exposure_bias, 0.35458f * exposure_bias, 0.04823f * exposure_bias),
vec3(0.07600f * exposure_bias, 0.90834f * exposure_bias, 0.01566f * exposure_bias),
vec3(0.02840f * exposure_bias, 0.13383f * exposure_bias, 0.83777f * exposure_bias));
const mat3 odt_to_rgb = mat3(
vec3(1.60475f, -0.53108f, -0.07367f),
vec3(-0.10208f, 1.10813f, -0.00605f),
vec3(-0.00327f, -0.07276f, 1.07602f));
color *= rgb_to_rrt;
vec3 color_tonemapped = (color * (color + A) - B) / (color * (C * color + D) + E);
color_tonemapped *= odt_to_rgb;
p_white *= exposure_bias;
float p_white_tonemapped = (p_white * (p_white + A) - B) / (p_white * (C * p_white + D) + E);
return color_tonemapped / p_white_tonemapped;
}
vec3 tonemap_reinhard(vec3 color, float p_white) {
return (p_white * color + color) / (color * p_white + p_white);
}
vec3 linear_to_srgb(vec3 color) {
//if going to srgb, clamp from 0 to 1.
color = clamp(color, vec3(0.0), vec3(1.0));
const vec3 a = vec3(0.055f);
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
}
#define TONEMAPPER_LINEAR 0
#define TONEMAPPER_REINHARD 1
#define TONEMAPPER_FILMIC 2
#define TONEMAPPER_ACES 3
vec3 apply_tonemapping(vec3 color, float p_white) { // inputs are LINEAR, always outputs clamped [0;1] color
// Ensure color values passed to tonemappers are positive.
// They can be negative in the case of negative lights, which leads to undesired behavior.
if (tonemapper == TONEMAPPER_LINEAR) {
return color;
} else if (tonemapper == TONEMAPPER_REINHARD) {
return tonemap_reinhard(max(vec3(0.0f), color), p_white);
} else if (tonemapper == TONEMAPPER_FILMIC) {
return tonemap_filmic(max(vec3(0.0f), color), p_white);
} else { // TONEMAPPER_ACES
return tonemap_aces(max(vec3(0.0f), color), p_white);
}
}

View File

@ -1278,13 +1278,13 @@ MaterialStorage::MaterialStorage() {
shader_data_request_func[RS::SHADER_SPATIAL] = nullptr; shader_data_request_func[RS::SHADER_SPATIAL] = nullptr;
shader_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_shader_func; shader_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_shader_func;
shader_data_request_func[RS::SHADER_PARTICLES] = nullptr; shader_data_request_func[RS::SHADER_PARTICLES] = nullptr;
shader_data_request_func[RS::SHADER_SKY] = nullptr; shader_data_request_func[RS::SHADER_SKY] = _create_sky_shader_func;
shader_data_request_func[RS::SHADER_FOG] = nullptr; shader_data_request_func[RS::SHADER_FOG] = nullptr;
material_data_request_func[RS::SHADER_SPATIAL] = nullptr; material_data_request_func[RS::SHADER_SPATIAL] = nullptr;
material_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_material_func; material_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_material_func;
material_data_request_func[RS::SHADER_PARTICLES] = nullptr; material_data_request_func[RS::SHADER_PARTICLES] = nullptr;
material_data_request_func[RS::SHADER_SKY] = nullptr; material_data_request_func[RS::SHADER_SKY] = _create_sky_material_func;
material_data_request_func[RS::SHADER_FOG] = nullptr; material_data_request_func[RS::SHADER_FOG] = nullptr;
static_assert(sizeof(GlobalVariables::Value) == 16); static_assert(sizeof(GlobalVariables::Value) == 16);
@ -1365,7 +1365,7 @@ MaterialStorage::MaterialStorage() {
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
actions.render_mode_defines["light_only"] = "#define MODE_LIGHT_ONLY\n"; actions.render_mode_defines["light_only"] = "#define MODE_LIGHT_ONLY\n";
actions.base_texture_binding_index = 1; actions.base_texture_binding_index = 0;
actions.base_uniform_string = ""; actions.base_uniform_string = "";
actions.global_buffer_array_variable = ""; actions.global_buffer_array_variable = "";
@ -1626,10 +1626,10 @@ ShaderCompiler::DefaultIdentifierActions actions;
actions.renames["COLOR"] = "color"; actions.renames["COLOR"] = "color";
actions.renames["ALPHA"] = "alpha"; actions.renames["ALPHA"] = "alpha";
actions.renames["EYEDIR"] = "cube_normal"; actions.renames["EYEDIR"] = "cube_normal";
actions.renames["POSITION"] = "params.position_multiplier.xyz"; actions.renames["POSITION"] = "position";
actions.renames["SKY_COORDS"] = "panorama_coords"; actions.renames["SKY_COORDS"] = "panorama_coords";
actions.renames["SCREEN_UV"] = "uv"; actions.renames["SCREEN_UV"] = "uv";
actions.renames["TIME"] = "params.time"; actions.renames["TIME"] = "time";
actions.renames["PI"] = _MKSTR(Math_PI); actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU); actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E); actions.renames["E"] = _MKSTR(Math_E);
@ -1660,15 +1660,12 @@ ShaderCompiler::DefaultIdentifierActions actions;
actions.renames["AT_CUBEMAP_PASS"] = "AT_CUBEMAP_PASS"; actions.renames["AT_CUBEMAP_PASS"] = "AT_CUBEMAP_PASS";
actions.renames["AT_HALF_RES_PASS"] = "AT_HALF_RES_PASS"; actions.renames["AT_HALF_RES_PASS"] = "AT_HALF_RES_PASS";
actions.renames["AT_QUARTER_RES_PASS"] = "AT_QUARTER_RES_PASS"; actions.renames["AT_QUARTER_RES_PASS"] = "AT_QUARTER_RES_PASS";
actions.custom_samplers["RADIANCE"] = "material_samplers[3]";
actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n"; actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n";
actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n"; actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n";
actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n"; actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n";
actions.sampler_array_name = "material_samplers";
actions.base_texture_binding_index = 1; actions.base_texture_binding_index = 1;
actions.texture_layout_set = 1; actions.texture_layout_set = 1;
actions.base_uniform_string = "material.";
actions.base_varying_index = 10; actions.base_varying_index = 10;
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
@ -2739,7 +2736,8 @@ void MaterialStorage::material_update_dependency(RID p_material, RendererStorage
} }
} }
// Canvas Shader Data /* Canvas Shader Data */
void CanvasShaderData::set_code(const String &p_code) { void CanvasShaderData::set_code(const String &p_code) {
// compile the shader // compile the shader
@ -2982,4 +2980,227 @@ GLES3::MaterialData *GLES3::_create_canvas_material_func(ShaderData *p_shader) {
return material_data; return material_data;
} }
////////////////////////////////////////////////////////////////////////////////
// SKY SHADER
void SkyShaderData::set_code(const String &p_code) {
//compile
code = p_code;
valid = false;
ubo_size = 0;
uniforms.clear();
if (code.is_empty()) {
return; //just invalid, but no error
}
ShaderCompiler::GeneratedCode gen_code;
ShaderCompiler::IdentifierActions actions;
actions.entry_point_stages["sky"] = ShaderCompiler::STAGE_FRAGMENT;
uses_time = false;
uses_half_res = false;
uses_quarter_res = false;
uses_position = false;
uses_light = false;
actions.render_mode_flags["use_half_res_pass"] = &uses_half_res;
actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res;
actions.usage_flag_pointers["TIME"] = &uses_time;
actions.usage_flag_pointers["POSITION"] = &uses_position;
actions.usage_flag_pointers["LIGHT0_ENABLED"] = &uses_light;
actions.usage_flag_pointers["LIGHT0_ENERGY"] = &uses_light;
actions.usage_flag_pointers["LIGHT0_DIRECTION"] = &uses_light;
actions.usage_flag_pointers["LIGHT0_COLOR"] = &uses_light;
actions.usage_flag_pointers["LIGHT0_SIZE"] = &uses_light;
actions.usage_flag_pointers["LIGHT1_ENABLED"] = &uses_light;
actions.usage_flag_pointers["LIGHT1_ENERGY"] = &uses_light;
actions.usage_flag_pointers["LIGHT1_DIRECTION"] = &uses_light;
actions.usage_flag_pointers["LIGHT1_COLOR"] = &uses_light;
actions.usage_flag_pointers["LIGHT1_SIZE"] = &uses_light;
actions.usage_flag_pointers["LIGHT2_ENABLED"] = &uses_light;
actions.usage_flag_pointers["LIGHT2_ENERGY"] = &uses_light;
actions.usage_flag_pointers["LIGHT2_DIRECTION"] = &uses_light;
actions.usage_flag_pointers["LIGHT2_COLOR"] = &uses_light;
actions.usage_flag_pointers["LIGHT2_SIZE"] = &uses_light;
actions.usage_flag_pointers["LIGHT3_ENABLED"] = &uses_light;
actions.usage_flag_pointers["LIGHT3_ENERGY"] = &uses_light;
actions.usage_flag_pointers["LIGHT3_DIRECTION"] = &uses_light;
actions.usage_flag_pointers["LIGHT3_COLOR"] = &uses_light;
actions.usage_flag_pointers["LIGHT3_SIZE"] = &uses_light;
actions.uniforms = &uniforms;
Error err = MaterialStorage::get_singleton()->shaders.compiler_sky.compile(RS::SHADER_SKY, code, &actions, path, gen_code);
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
if (version.is_null()) {
version = MaterialStorage::get_singleton()->shaders.sky_shader.version_create();
}
#if 0
print_line("**compiling shader:");
print_line("**defines:\n");
for (int i = 0; i < gen_code.defines.size(); i++) {
print_line(gen_code.defines[i]);
}
print_line("\n**uniforms:\n" + gen_code.uniforms);
// print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
// print_line("\n**vertex_code:\n" + gen_code.vertex);
print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
print_line("\n**fragment_code:\n" + gen_code.fragment);
print_line("\n**light_code:\n" + gen_code.light);
#endif
Vector<StringName> texture_uniform_names;
for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
}
MaterialStorage::get_singleton()->shaders.sky_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names);
ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.sky_shader.version_is_valid(version));
ubo_size = gen_code.uniform_total_size;
ubo_offsets = gen_code.uniform_offsets;
texture_uniforms = gen_code.texture_uniforms;
valid = true;
}
void SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
default_texture_params[p_name].erase(p_index);
if (default_texture_params[p_name].is_empty()) {
default_texture_params.erase(p_name);
}
}
} else {
if (!default_texture_params.has(p_name)) {
default_texture_params[p_name] = Map<int, RID>();
}
default_texture_params[p_name][p_index] = p_texture;
}
}
void SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
Map<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
if (E.value.texture_order >= 0) {
order[E.value.texture_order + 100000] = E.key;
} else {
order[E.value.order] = E.key;
}
}
for (const KeyValue<int, StringName> &E : order) {
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
}
}
void SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
}
RendererMaterialStorage::InstanceShaderParam p;
p.info = ShaderLanguage::uniform_to_property_info(E.value);
p.info.name = E.key; //supply name
p.index = E.value.instance_index;
p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
p_param_list->push_back(p);
}
}
bool SkyShaderData::is_param_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
}
return uniforms[p_param].texture_order >= 0;
}
bool SkyShaderData::is_animated() const {
return false;
}
bool SkyShaderData::casts_shadows() const {
return false;
}
Variant SkyShaderData::get_default_parameter(const StringName &p_parameter) const {
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
}
return Variant();
}
RS::ShaderNativeSourceCode SkyShaderData::get_native_source_code() const {
return MaterialStorage::get_singleton()->shaders.sky_shader.version_get_native_source_code(version);
}
SkyShaderData::SkyShaderData() {
valid = false;
}
SkyShaderData::~SkyShaderData() {
if (version.is_valid()) {
MaterialStorage::get_singleton()->shaders.sky_shader.version_free(version);
}
}
GLES3::ShaderData *GLES3::_create_sky_shader_func() {
SkyShaderData *shader_data = memnew(SkyShaderData);
return shader_data;
}
////////////////////////////////////////////////////////////////////////////////
// Sky material
void SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
return update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size);
}
SkyMaterialData::~SkyMaterialData() {
}
GLES3::MaterialData *GLES3::_create_sky_material_func(ShaderData *p_shader) {
SkyMaterialData *material_data = memnew(SkyMaterialData);
material_data->shader_data = static_cast<SkyShaderData *>(p_shader);
//update will happen later anyway so do nothing.
return material_data;
}
void SkyMaterialData::bind_uniforms() {
// Bind Material Uniforms
glBindBufferBase(GL_UNIFORM_BUFFER, 3, uniform_buffer);
RID *textures = texture_cache.ptrw();
ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
for (int ti = 0; ti < texture_cache.size(); ti++) {
Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
glActiveTexture(GL_TEXTURE0 + ti);
glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
// Set sampler state here as the same texture can be used in multiple places with different flags
// Need to convert sampler state from ShaderLanguage::Texture* to RS::CanvasItemTexture*
RS::CanvasItemTextureFilter filter = RS::CanvasItemTextureFilter((int(texture_uniforms[ti].filter) + 1) % RS::CANVAS_ITEM_TEXTURE_FILTER_MAX);
RS::CanvasItemTextureRepeat repeat = RS::CanvasItemTextureRepeat((int(texture_uniforms[ti].repeat) + 1) % RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR);
texture->gl_set_filter(filter);
texture->gl_set_repeat(repeat);
}
}
#endif // !GLES3_ENABLED #endif // !GLES3_ENABLED

View File

@ -200,6 +200,55 @@ struct CanvasMaterialData : public MaterialData {
MaterialData *_create_canvas_material_func(ShaderData *p_shader); MaterialData *_create_canvas_material_func(ShaderData *p_shader);
/* Sky Materials */
struct SkyShaderData : public ShaderData {
bool valid;
RID version;
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size;
String path;
String code;
Map<StringName, Map<int, RID>> default_texture_params;
bool uses_time;
bool uses_position;
bool uses_half_res;
bool uses_quarter_res;
bool uses_light;
virtual void set_code(const String &p_Code);
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
virtual bool is_param_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
SkyShaderData();
virtual ~SkyShaderData();
};
ShaderData *_create_sky_shader_func();
struct SkyMaterialData : public MaterialData {
SkyShaderData *shader_data = nullptr;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
virtual void bind_uniforms();
virtual ~SkyMaterialData();
};
MaterialData *_create_sky_material_func(ShaderData *p_shader);
/* Global variable structs */ /* Global variable structs */
struct GlobalVariables { struct GlobalVariables {
enum { enum {

View File

@ -388,6 +388,9 @@ public:
/* MESH INSTANCE API */ /* MESH INSTANCE API */
MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); };
bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); };
virtual RID mesh_instance_create(RID p_base) override; virtual RID mesh_instance_create(RID p_base) override;
virtual void mesh_instance_free(RID p_rid) override; virtual void mesh_instance_free(RID p_rid) override;
virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override; virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override;
@ -431,6 +434,9 @@ public:
/* MULTIMESH API */ /* MULTIMESH API */
MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); };
bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); };
virtual RID multimesh_allocate() override; virtual RID multimesh_allocate() override;
virtual void multimesh_initialize(RID p_rid) override; virtual void multimesh_initialize(RID p_rid) override;
virtual void multimesh_free(RID p_rid) override; virtual void multimesh_free(RID p_rid) override;
@ -483,6 +489,9 @@ public:
/* SKELETON API */ /* SKELETON API */
Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); };
bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); };
virtual RID skeleton_allocate() override; virtual RID skeleton_allocate() override;
virtual void skeleton_initialize(RID p_rid) override; virtual void skeleton_initialize(RID p_rid) override;
virtual void skeleton_free(RID p_rid) override; virtual void skeleton_free(RID p_rid) override;

View File

@ -95,9 +95,9 @@ public:
static void make_current() { static void make_current() {
_create_func = _create_current; _create_func = _create_current;
low_end = true;
} }
bool is_low_end() const override { return true; }
uint64_t get_frame_number() const override { return frame; } uint64_t get_frame_number() const override { return frame; }
double get_frame_delta_time() const override { return delta; } double get_frame_delta_time() const override { return delta; }

View File

@ -35,6 +35,7 @@
#include "core/string/print_string.h" #include "core/string/print_string.h"
RendererCompositor *(*RendererCompositor::_create_func)() = nullptr; RendererCompositor *(*RendererCompositor::_create_func)() = nullptr;
bool RendererCompositor::low_end = false;
RendererCompositor *RendererCompositor::create() { RendererCompositor *RendererCompositor::create() {
return _create_func(); return _create_func();

View File

@ -71,6 +71,7 @@ private:
protected: protected:
static RendererCompositor *(*_create_func)(); static RendererCompositor *(*_create_func)();
bool back_end = false; bool back_end = false;
static bool low_end;
public: public:
static RendererCompositor *create(); static RendererCompositor *create();
@ -97,7 +98,7 @@ public:
virtual uint64_t get_frame_number() const = 0; virtual uint64_t get_frame_number() const = 0;
virtual double get_frame_delta_time() const = 0; virtual double get_frame_delta_time() const = 0;
_FORCE_INLINE_ virtual bool is_low_end() const { return back_end; }; static bool is_low_end() { return low_end; };
virtual bool is_xr_enabled() const; virtual bool is_xr_enabled() const;
RendererCompositor(); RendererCompositor();

View File

@ -131,6 +131,7 @@ public:
static void make_current() { static void make_current() {
_create_func = _create_current; _create_func = _create_current;
low_end = false;
} }
static RendererCompositorRD *singleton; static RendererCompositorRD *singleton;

View File

@ -321,11 +321,7 @@ void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) {
} }
bool RenderingServerDefault::is_low_end() const { bool RenderingServerDefault::is_low_end() const {
// FIXME: Commented out when rebasing vulkan branch on master, return RendererCompositor::is_low_end();
// causes a crash, it seems rasterizer is not initialized yet the
// first time it's called.
//return RSG::rasterizer->is_low_end();
return false;
} }
void RenderingServerDefault::_thread_exit() { void RenderingServerDefault::_thread_exit() {

View File

@ -113,7 +113,9 @@ public:
_changes_changed(); _changes_changed();
#else #else
_FORCE_INLINE_ static void redraw_request() { changes++; } _FORCE_INLINE_ static void redraw_request() {
changes++;
}
#endif #endif
#define WRITE_ACTION redraw_request(); #define WRITE_ACTION redraw_request();

View File

@ -48,8 +48,8 @@ static String _mktab(int p_level) {
static String _typestr(SL::DataType p_type) { static String _typestr(SL::DataType p_type) {
String type = ShaderLanguage::get_datatype_name(p_type); String type = ShaderLanguage::get_datatype_name(p_type);
if (ShaderLanguage::is_sampler_type(p_type)) { if (!RS::get_singleton()->is_low_end() && ShaderLanguage::is_sampler_type(p_type)) {
type = type.replace("sampler", "texture"); //we use textures instead of samplers type = type.replace("sampler", "texture"); //we use textures instead of samplers in Vulkan GLSL
} }
return type; return type;
} }
@ -538,7 +538,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
continue; // Instances are indexed directly, don't need index uniforms. continue; // Instances are indexed directly, don't need index uniforms.
} }
if (SL::is_sampler_type(uniform.type)) { if (SL::is_sampler_type(uniform.type)) {
ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") uniform "; // Texture layouts are different for OpenGL GLSL and Vulkan GLSL
if (!RS::get_singleton()->is_low_end()) {
ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") ";
}
ucode += "uniform ";
} }
bool is_buffer_global = !SL::is_sampler_type(uniform.type) && uniform.scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL; bool is_buffer_global = !SL::is_sampler_type(uniform.type) && uniform.scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL;
@ -1125,8 +1129,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
code += ", "; code += ", ";
} }
String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
if (is_texture_func && i == 1) { if (!RS::get_singleton()->is_low_end() && is_texture_func && i == 1) {
//need to map from texture to sampler in order to sample //need to map from texture to sampler in order to sample when using Vulkan GLSL
StringName texture_uniform; StringName texture_uniform;
bool correct_texture_uniform = false; bool correct_texture_uniform = false;