mirror of
https://github.com/godotengine/godot
synced 2024-09-05 15:19:59 +00:00
SkyShaders working
This commit is contained in:
parent
516ec892b4
commit
3bb8e6a9fe
|
@ -92,9 +92,9 @@ public:
|
|||
|
||||
static void make_current() {
|
||||
_create_func = _create_current;
|
||||
low_end = true;
|
||||
}
|
||||
|
||||
virtual bool is_low_end() const { return true; }
|
||||
uint64_t get_frame_number() const { return frame; }
|
||||
double get_frame_delta_time() const { return delta; }
|
||||
|
||||
|
|
|
@ -238,37 +238,81 @@ void RasterizerSceneGLES3::_update_dirty_skys() {
|
|||
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) {
|
||||
ERR_FAIL_COND(!p_sky);
|
||||
void RasterizerSceneGLES3::_draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform) {
|
||||
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
|
||||
ERR_FAIL_COND(!p_env);
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_BLEND);
|
||||
Sky *sky = sky_owner.get_or_null(p_env->sky);
|
||||
ERR_FAIL_COND(!sky);
|
||||
|
||||
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);
|
||||
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, 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
|
||||
//glBindBufferBase(GL_UNIFORM_BUFFER, 2, p_sky.directional light data); // Directional light data
|
||||
|
||||
// Camera
|
||||
CameraMatrix camera;
|
||||
|
||||
if (p_custom_fov) {
|
||||
if (p_env->sky_custom_fov) {
|
||||
float near_plane = p_projection.get_z_near();
|
||||
float far_plane = p_projection.get_z_far();
|
||||
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 {
|
||||
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);
|
||||
|
||||
//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) {
|
||||
|
@ -674,12 +718,14 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
|
|||
Environment *env = environment_owner.get_or_null(p_environment);
|
||||
|
||||
bool fb_cleared = false;
|
||||
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
/* Depth Prepass */
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rb->framebuffer);
|
||||
glViewport(0, 0, rb->width, rb->height);
|
||||
|
||||
if (!fb_cleared) {
|
||||
glClearDepth(1.0f);
|
||||
|
@ -730,7 +776,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
|
|||
}
|
||||
|
||||
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()) {
|
||||
|
@ -1014,9 +1060,9 @@ RasterizerSceneGLES3::RasterizerSceneGLES3(RasterizerStorageGLES3 *p_storage) {
|
|||
String global_defines;
|
||||
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";
|
||||
state.sky_shader.initialize(global_defines);
|
||||
sky_globals.shader_default_version = state.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.initialize(global_defines);
|
||||
sky_globals.shader_default_version = GLES3::MaterialStorage::get_singleton()->shaders.sky_shader.version_create();
|
||||
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);
|
||||
}
|
||||
{
|
||||
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() {
|
||||
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_shader);
|
||||
storage->free(sky_globals.fog_material);
|
||||
storage->free(sky_globals.fog_shader);
|
||||
}
|
||||
|
||||
#endif // GLES3_ENABLED
|
||||
|
|
|
@ -97,6 +97,10 @@ private:
|
|||
RID shader_default_version;
|
||||
RID default_material;
|
||||
RID default_shader;
|
||||
RID fog_material;
|
||||
RID fog_shader;
|
||||
GLuint quad = 0;
|
||||
GLuint quad_array = 0;
|
||||
uint32_t max_directional_lights = 4;
|
||||
uint32_t roughness_layers = 8;
|
||||
uint32_t ggx_samples = 128;
|
||||
|
@ -319,7 +323,7 @@ protected:
|
|||
Sky *dirty_list = nullptr;
|
||||
|
||||
//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);
|
||||
float prev_time = 0.0f;
|
||||
|
||||
|
@ -335,17 +339,12 @@ protected:
|
|||
|
||||
void _invalidate_sky(Sky *p_sky);
|
||||
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:
|
||||
RasterizerStorageGLES3 *storage;
|
||||
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;
|
||||
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;
|
||||
|
|
|
@ -342,25 +342,13 @@ void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder,
|
|||
*/
|
||||
|
||||
RS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const {
|
||||
return RS::INSTANCE_NONE;
|
||||
|
||||
/*
|
||||
if (mesh_owner.owns(p_rid)) {
|
||||
if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
|
||||
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) {
|
||||
|
@ -379,80 +367,19 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
|
|||
} else if (GLES3::MaterialStorage::get_singleton()->owns_material(p_rid)) {
|
||||
GLES3::MaterialStorage::get_singleton()->material_free(p_rid);
|
||||
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 {
|
||||
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)) {
|
||||
Light *light = light_owner.get_or_null(p_rid);
|
||||
light->instance_remove_deps();
|
||||
|
|
|
@ -20,6 +20,15 @@ layout(location = 4) in vec2 uv_attrib;
|
|||
layout(location = 10) in uvec4 bone_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
|
||||
/* clang-format on */
|
||||
#include "canvas_uniforms_inc.glsl"
|
||||
|
@ -38,15 +47,6 @@ out vec2 pixel_size_interp;
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(std140) uniform MaterialUniforms{
|
||||
//ubo:4
|
||||
|
||||
#MATERIAL_UNIFORMS
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
#GLOBALS
|
||||
|
||||
void main() {
|
||||
|
|
|
@ -26,9 +26,9 @@ out vec2 uv_interp;
|
|||
|
||||
void main() {
|
||||
// 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];
|
||||
gl_Position = vec4(uv_interp, 1.0, 1.0);
|
||||
gl_Position = vec4(uv_interp, 0.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
|
@ -50,6 +50,8 @@ precision mediump int;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#include "tonemap_inc.glsl"
|
||||
|
||||
in vec2 uv_interp;
|
||||
|
||||
/* clang-format on */
|
||||
|
@ -63,12 +65,7 @@ uniform sampler2D half_res; //texunit:-2
|
|||
uniform sampler2D quarter_res; //texunit:-3
|
||||
#endif
|
||||
|
||||
layout(std140) uniform CanvasData { //ubo:0
|
||||
mat3 orientation;
|
||||
vec4 projection;
|
||||
vec4 position_multiplier;
|
||||
float time;
|
||||
float luminance_multiplier;
|
||||
layout(std140) uniform SceneData { //ubo:0
|
||||
float pad1;
|
||||
float pad2;
|
||||
};
|
||||
|
@ -88,15 +85,16 @@ layout(std140) uniform DirectionalLights { //ubo:2
|
|||
}
|
||||
directional_lights;
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(std140) uniform MaterialUniforms{
|
||||
//ubo:3
|
||||
layout(std140) uniform MaterialUniforms{ //ubo:3
|
||||
|
||||
#MATERIAL_UNIFORMS
|
||||
|
||||
} material;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* clang-format on */
|
||||
#GLOBALS
|
||||
|
||||
#ifdef USE_CUBEMAP_PASS
|
||||
|
@ -117,6 +115,12 @@ layout(std140) uniform MaterialUniforms{
|
|||
#define AT_QUARTER_RES_PASS false
|
||||
#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;
|
||||
|
||||
void main() {
|
||||
|
@ -128,7 +132,7 @@ void main() {
|
|||
cube_normal.z = -cube_normal.z;
|
||||
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));
|
||||
|
||||
|
@ -148,17 +152,17 @@ void main() {
|
|||
vec3 inverted_cube_normal = cube_normal;
|
||||
inverted_cube_normal.z *= -1.0;
|
||||
#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
|
||||
#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
|
||||
#else
|
||||
#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
|
||||
#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
|
||||
|
||||
|
@ -168,12 +172,19 @@ void main() {
|
|||
|
||||
}
|
||||
|
||||
frag_color.rgb = color * position_multiplier.w / luminance_multiplier;
|
||||
frag_color.a = alpha;
|
||||
// Tonemap before writing as we are writing to an sRGB framebuffer
|
||||
color *= exposure;
|
||||
color = apply_tonemapping(color, white);
|
||||
color = linear_to_srgb(color);
|
||||
|
||||
// Blending is disabled for Sky, so alpha doesn't blend
|
||||
// alpha is used for subsurface scattering so make sure it doesn't get applied to Sky
|
||||
if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) {
|
||||
frag_color.a = 0.0;
|
||||
}
|
||||
#ifdef USE_BCS
|
||||
color = apply_bcs(color, bcs);
|
||||
#endif
|
||||
|
||||
#ifdef USE_COLOR_CORRECTION
|
||||
color = apply_color_correction(color, color_correction);
|
||||
#endif
|
||||
|
||||
frag_color.rgb = color;
|
||||
frag_color.a = alpha;
|
||||
}
|
||||
|
|
117
drivers/gles3/shaders/tonemap_inc.glsl
Normal file
117
drivers/gles3/shaders/tonemap_inc.glsl
Normal 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);
|
||||
}
|
||||
}
|
|
@ -1278,13 +1278,13 @@ MaterialStorage::MaterialStorage() {
|
|||
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_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;
|
||||
|
||||
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_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;
|
||||
|
||||
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["light_only"] = "#define MODE_LIGHT_ONLY\n";
|
||||
|
||||
actions.base_texture_binding_index = 1;
|
||||
actions.base_texture_binding_index = 0;
|
||||
actions.base_uniform_string = "";
|
||||
actions.global_buffer_array_variable = "";
|
||||
|
||||
|
@ -1626,10 +1626,10 @@ ShaderCompiler::DefaultIdentifierActions actions;
|
|||
actions.renames["COLOR"] = "color";
|
||||
actions.renames["ALPHA"] = "alpha";
|
||||
actions.renames["EYEDIR"] = "cube_normal";
|
||||
actions.renames["POSITION"] = "params.position_multiplier.xyz";
|
||||
actions.renames["POSITION"] = "position";
|
||||
actions.renames["SKY_COORDS"] = "panorama_coords";
|
||||
actions.renames["SCREEN_UV"] = "uv";
|
||||
actions.renames["TIME"] = "params.time";
|
||||
actions.renames["TIME"] = "time";
|
||||
actions.renames["PI"] = _MKSTR(Math_PI);
|
||||
actions.renames["TAU"] = _MKSTR(Math_TAU);
|
||||
actions.renames["E"] = _MKSTR(Math_E);
|
||||
|
@ -1660,15 +1660,12 @@ ShaderCompiler::DefaultIdentifierActions actions;
|
|||
actions.renames["AT_CUBEMAP_PASS"] = "AT_CUBEMAP_PASS";
|
||||
actions.renames["AT_HALF_RES_PASS"] = "AT_HALF_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["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n";
|
||||
actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n";
|
||||
|
||||
actions.sampler_array_name = "material_samplers";
|
||||
actions.base_texture_binding_index = 1;
|
||||
actions.texture_layout_set = 1;
|
||||
actions.base_uniform_string = "material.";
|
||||
actions.base_varying_index = 10;
|
||||
|
||||
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) {
|
||||
// compile the shader
|
||||
|
||||
|
@ -2982,4 +2980,227 @@ GLES3::MaterialData *GLES3::_create_canvas_material_func(ShaderData *p_shader) {
|
|||
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
|
||||
|
|
|
@ -200,6 +200,55 @@ struct CanvasMaterialData : public MaterialData {
|
|||
|
||||
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 */
|
||||
struct GlobalVariables {
|
||||
enum {
|
||||
|
|
|
@ -388,6 +388,9 @@ public:
|
|||
|
||||
/* 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 void mesh_instance_free(RID p_rid) override;
|
||||
virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override;
|
||||
|
@ -431,6 +434,9 @@ public:
|
|||
|
||||
/* 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 void multimesh_initialize(RID p_rid) override;
|
||||
virtual void multimesh_free(RID p_rid) override;
|
||||
|
@ -483,6 +489,9 @@ public:
|
|||
|
||||
/* 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 void skeleton_initialize(RID p_rid) override;
|
||||
virtual void skeleton_free(RID p_rid) override;
|
||||
|
|
|
@ -95,9 +95,9 @@ public:
|
|||
|
||||
static void make_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; }
|
||||
double get_frame_delta_time() const override { return delta; }
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "core/string/print_string.h"
|
||||
|
||||
RendererCompositor *(*RendererCompositor::_create_func)() = nullptr;
|
||||
bool RendererCompositor::low_end = false;
|
||||
|
||||
RendererCompositor *RendererCompositor::create() {
|
||||
return _create_func();
|
||||
|
|
|
@ -71,6 +71,7 @@ private:
|
|||
protected:
|
||||
static RendererCompositor *(*_create_func)();
|
||||
bool back_end = false;
|
||||
static bool low_end;
|
||||
|
||||
public:
|
||||
static RendererCompositor *create();
|
||||
|
@ -97,7 +98,7 @@ public:
|
|||
virtual uint64_t get_frame_number() 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;
|
||||
|
||||
RendererCompositor();
|
||||
|
|
|
@ -131,6 +131,7 @@ public:
|
|||
|
||||
static void make_current() {
|
||||
_create_func = _create_current;
|
||||
low_end = false;
|
||||
}
|
||||
|
||||
static RendererCompositorRD *singleton;
|
||||
|
|
|
@ -321,11 +321,7 @@ void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) {
|
|||
}
|
||||
|
||||
bool RenderingServerDefault::is_low_end() const {
|
||||
// FIXME: Commented out when rebasing vulkan branch on master,
|
||||
// causes a crash, it seems rasterizer is not initialized yet the
|
||||
// first time it's called.
|
||||
//return RSG::rasterizer->is_low_end();
|
||||
return false;
|
||||
return RendererCompositor::is_low_end();
|
||||
}
|
||||
|
||||
void RenderingServerDefault::_thread_exit() {
|
||||
|
|
|
@ -113,7 +113,9 @@ public:
|
|||
_changes_changed();
|
||||
|
||||
#else
|
||||
_FORCE_INLINE_ static void redraw_request() { changes++; }
|
||||
_FORCE_INLINE_ static void redraw_request() {
|
||||
changes++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define WRITE_ACTION redraw_request();
|
||||
|
|
|
@ -48,8 +48,8 @@ static String _mktab(int p_level) {
|
|||
|
||||
static String _typestr(SL::DataType p_type) {
|
||||
String type = ShaderLanguage::get_datatype_name(p_type);
|
||||
if (ShaderLanguage::is_sampler_type(p_type)) {
|
||||
type = type.replace("sampler", "texture"); //we use textures instead of samplers
|
||||
if (!RS::get_singleton()->is_low_end() && ShaderLanguage::is_sampler_type(p_type)) {
|
||||
type = type.replace("sampler", "texture"); //we use textures instead of samplers in Vulkan GLSL
|
||||
}
|
||||
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.
|
||||
}
|
||||
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;
|
||||
|
@ -1125,8 +1129,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
|
|||
code += ", ";
|
||||
}
|
||||
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) {
|
||||
//need to map from texture to sampler in order to sample
|
||||
if (!RS::get_singleton()->is_low_end() && is_texture_func && i == 1) {
|
||||
//need to map from texture to sampler in order to sample when using Vulkan GLSL
|
||||
StringName texture_uniform;
|
||||
bool correct_texture_uniform = false;
|
||||
|
||||
|
|
Loading…
Reference in a new issue