mirror of
https://github.com/godotengine/godot.git
synced 2025-12-08 06:09:55 +00:00
Renaming of servers for coherency.
VisualServer -> RenderingServer PhysicsServer -> PhysicsServer3D Physics2DServer -> PhysicsServer2D NavigationServer -> NavigationServer3D Navigation2DServer -> NavigationServer2D Also renamed corresponding files.
This commit is contained in:
parent
307b1b3a58
commit
a6f3bc7c69
390 changed files with 10701 additions and 10702 deletions
7
servers/rendering/SCsub
Normal file
7
servers/rendering/SCsub
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
Import('env')
|
||||
|
||||
env.add_source_files(env.servers_sources, "*.cpp")
|
||||
|
||||
SConscript("rasterizer_rd/SCsub")
|
||||
77
servers/rendering/rasterizer.cpp
Normal file
77
servers/rendering/rasterizer.cpp
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*************************************************************************/
|
||||
/* rasterizer.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "rasterizer.h"
|
||||
|
||||
#include "core/os/os.h"
|
||||
#include "core/print_string.h"
|
||||
|
||||
Rasterizer *(*Rasterizer::_create_func)() = NULL;
|
||||
|
||||
void RasterizerScene::InstanceDependency::instance_notify_changed(bool p_aabb, bool p_dependencies) {
|
||||
for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
|
||||
E->key()->dependency_changed(p_aabb, p_dependencies);
|
||||
}
|
||||
}
|
||||
void RasterizerScene::InstanceDependency::instance_notify_deleted(RID p_deleted) {
|
||||
for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
|
||||
E->key()->dependency_deleted(p_deleted);
|
||||
}
|
||||
for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
|
||||
E->key()->dependencies.erase(this);
|
||||
}
|
||||
|
||||
instances.clear();
|
||||
}
|
||||
|
||||
RasterizerScene::InstanceDependency::~InstanceDependency() {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (instances.size()) {
|
||||
WARN_PRINT("Leaked instance dependency: Bug - did not call instance_notify_deleted when freeing.");
|
||||
for (Map<InstanceBase *, uint32_t>::Element *E = instances.front(); E; E = E->next()) {
|
||||
E->key()->dependencies.erase(this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Rasterizer *Rasterizer::create() {
|
||||
|
||||
return _create_func();
|
||||
}
|
||||
|
||||
RasterizerCanvas *RasterizerCanvas::singleton = NULL;
|
||||
|
||||
RasterizerStorage *RasterizerStorage::base_singleton = NULL;
|
||||
|
||||
RasterizerStorage::RasterizerStorage() {
|
||||
|
||||
base_singleton = this;
|
||||
}
|
||||
1307
servers/rendering/rasterizer.h
Normal file
1307
servers/rendering/rasterizer.h
Normal file
File diff suppressed because it is too large
Load diff
7
servers/rendering/rasterizer_rd/SCsub
Normal file
7
servers/rendering/rasterizer_rd/SCsub
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
Import('env')
|
||||
|
||||
env.add_source_files(env.servers_sources, "*.cpp")
|
||||
|
||||
SConscript("shaders/SCsub")
|
||||
28
servers/rendering/rasterizer_rd/cubemap_coeffs.h
Normal file
28
servers/rendering/rasterizer_rd/cubemap_coeffs.h
Normal file
File diff suppressed because one or more lines are too long
255
servers/rendering/rasterizer_rd/light_cluster_builder.cpp
Normal file
255
servers/rendering/rasterizer_rd/light_cluster_builder.cpp
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
/*************************************************************************/
|
||||
/* light_cluster_builder.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "light_cluster_builder.h"
|
||||
|
||||
void LightClusterBuilder::begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection) {
|
||||
view_xform = p_view_transform;
|
||||
projection = p_cam_projection;
|
||||
z_near = -projection.get_z_near();
|
||||
z_far = -projection.get_z_far();
|
||||
|
||||
//reset counts
|
||||
light_count = 0;
|
||||
refprobe_count = 0;
|
||||
item_count = 0;
|
||||
sort_id_count = 0;
|
||||
}
|
||||
|
||||
void LightClusterBuilder::bake_cluster() {
|
||||
|
||||
float slice_depth = (z_near - z_far) / depth;
|
||||
|
||||
uint8_t *cluster_dataw = cluster_data.ptrw();
|
||||
Cell *cluster_data_ptr = (Cell *)cluster_dataw;
|
||||
//clear the cluster
|
||||
zeromem(cluster_data_ptr, (width * height * depth * sizeof(Cell)));
|
||||
|
||||
/* Step 1, create cell positions and count them */
|
||||
|
||||
for (uint32_t i = 0; i < item_count; i++) {
|
||||
|
||||
const Item &item = items[i];
|
||||
|
||||
int from_slice = Math::floor((z_near - (item.aabb.position.z + item.aabb.size.z)) / slice_depth);
|
||||
int to_slice = Math::floor((z_near - item.aabb.position.z) / slice_depth);
|
||||
|
||||
if (from_slice >= (int)depth || to_slice < 0) {
|
||||
continue; //sorry no go
|
||||
}
|
||||
|
||||
from_slice = MAX(0, from_slice);
|
||||
to_slice = MIN((int)depth - 1, to_slice);
|
||||
|
||||
for (int j = from_slice; j <= to_slice; j++) {
|
||||
|
||||
Vector3 min = item.aabb.position;
|
||||
Vector3 max = item.aabb.position + item.aabb.size;
|
||||
|
||||
float limit_near = MIN((z_near - slice_depth * j), max.z);
|
||||
float limit_far = MAX((z_near - slice_depth * (j + 1)), min.z);
|
||||
|
||||
max.z = limit_near;
|
||||
min.z = limit_near;
|
||||
|
||||
Vector3 proj_min = projection.xform(min);
|
||||
Vector3 proj_max = projection.xform(max);
|
||||
|
||||
int near_from_x = int(Math::floor((proj_min.x * 0.5 + 0.5) * width));
|
||||
int near_from_y = int(Math::floor((-proj_max.y * 0.5 + 0.5) * height));
|
||||
int near_to_x = int(Math::floor((proj_max.x * 0.5 + 0.5) * width));
|
||||
int near_to_y = int(Math::floor((-proj_min.y * 0.5 + 0.5) * height));
|
||||
|
||||
max.z = limit_far;
|
||||
min.z = limit_far;
|
||||
|
||||
proj_min = projection.xform(min);
|
||||
proj_max = projection.xform(max);
|
||||
|
||||
int far_from_x = int(Math::floor((proj_min.x * 0.5 + 0.5) * width));
|
||||
int far_from_y = int(Math::floor((-proj_max.y * 0.5 + 0.5) * height));
|
||||
int far_to_x = int(Math::floor((proj_max.x * 0.5 + 0.5) * width));
|
||||
int far_to_y = int(Math::floor((-proj_min.y * 0.5 + 0.5) * height));
|
||||
|
||||
//print_line(itos(j) + " near - " + Vector2i(near_from_x, near_from_y) + " -> " + Vector2i(near_to_x, near_to_y));
|
||||
//print_line(itos(j) + " far - " + Vector2i(far_from_x, far_from_y) + " -> " + Vector2i(far_to_x, far_to_y));
|
||||
|
||||
int from_x = MIN(near_from_x, far_from_x);
|
||||
int from_y = MIN(near_from_y, far_from_y);
|
||||
int to_x = MAX(near_to_x, far_to_x);
|
||||
int to_y = MAX(near_to_y, far_to_y);
|
||||
|
||||
if (from_x >= (int)width || to_x < 0 || from_y >= (int)height || to_y < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int sx = MAX(0, from_x);
|
||||
int sy = MAX(0, from_y);
|
||||
int dx = MIN((int)width - 1, to_x);
|
||||
int dy = MIN((int)height - 1, to_y);
|
||||
|
||||
//print_line(itos(j) + " - " + Vector2i(sx, sy) + " -> " + Vector2i(dx, dy));
|
||||
|
||||
for (int x = sx; x <= dx; x++) {
|
||||
for (int y = sy; y <= dy; y++) {
|
||||
uint32_t offset = j * (width * height) + y * width + x;
|
||||
|
||||
if (unlikely(sort_id_count == sort_id_max)) {
|
||||
sort_id_max = nearest_power_of_2_templated(sort_id_max + 1);
|
||||
sort_ids = (SortID *)memrealloc(sort_ids, sizeof(SortID) * sort_id_max);
|
||||
if (ids.size()) {
|
||||
|
||||
ids.resize(sort_id_max);
|
||||
RD::get_singleton()->free(items_buffer);
|
||||
items_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * sort_id_max);
|
||||
}
|
||||
}
|
||||
|
||||
sort_ids[sort_id_count].cell_index = offset;
|
||||
sort_ids[sort_id_count].item_index = item.index;
|
||||
sort_ids[sort_id_count].item_type = item.type;
|
||||
|
||||
sort_id_count++;
|
||||
|
||||
//for now, only count
|
||||
cluster_data_ptr[offset].item_pointers[item.type]++;
|
||||
//print_line("at offset " + itos(offset) + " value: " + itos(cluster_data_ptr[offset].item_pointers[item.type]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 2, Assign pointers (and reset counters) */
|
||||
|
||||
uint32_t offset = 0;
|
||||
for (uint32_t i = 0; i < (width * height * depth); i++) {
|
||||
for (int j = 0; j < ITEM_TYPE_MAX; j++) {
|
||||
uint32_t count = cluster_data_ptr[i].item_pointers[j]; //save count
|
||||
cluster_data_ptr[i].item_pointers[j] = offset; //replace count by pointer
|
||||
offset += count; //increase offset by count;
|
||||
}
|
||||
}
|
||||
|
||||
//print_line("offset: " + itos(offset));
|
||||
/* Step 3, Place item lists */
|
||||
|
||||
uint32_t *ids_ptr = ids.ptrw();
|
||||
|
||||
for (uint32_t i = 0; i < sort_id_count; i++) {
|
||||
const SortID &id = sort_ids[i];
|
||||
Cell &cell = cluster_data_ptr[id.cell_index];
|
||||
uint32_t pointer = cell.item_pointers[id.item_type] & POINTER_MASK;
|
||||
uint32_t counter = cell.item_pointers[id.item_type] >> COUNTER_SHIFT;
|
||||
ids_ptr[pointer + counter] = id.item_index;
|
||||
|
||||
cell.item_pointers[id.item_type] = pointer | ((counter + 1) << COUNTER_SHIFT);
|
||||
}
|
||||
|
||||
RD::get_singleton()->texture_update(cluster_texture, 0, cluster_data, true);
|
||||
RD::get_singleton()->buffer_update(items_buffer, 0, offset * sizeof(uint32_t), ids_ptr, true);
|
||||
}
|
||||
|
||||
void LightClusterBuilder::setup(uint32_t p_width, uint32_t p_height, uint32_t p_depth) {
|
||||
|
||||
if (width == p_width && height == p_height && depth == p_depth) {
|
||||
return;
|
||||
}
|
||||
if (cluster_texture.is_valid()) {
|
||||
RD::get_singleton()->free(cluster_texture);
|
||||
}
|
||||
|
||||
width = p_width;
|
||||
height = p_height;
|
||||
depth = p_depth;
|
||||
|
||||
cluster_data.resize(width * height * depth * sizeof(Cell));
|
||||
|
||||
{
|
||||
RD::TextureFormat tf;
|
||||
tf.format = RD::DATA_FORMAT_R32G32B32A32_UINT;
|
||||
tf.type = RD::TEXTURE_TYPE_3D;
|
||||
tf.width = width;
|
||||
tf.height = height;
|
||||
tf.depth = depth;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
|
||||
|
||||
cluster_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
}
|
||||
}
|
||||
|
||||
RID LightClusterBuilder::get_cluster_texture() const {
|
||||
return cluster_texture;
|
||||
}
|
||||
RID LightClusterBuilder::get_cluster_indices_buffer() const {
|
||||
return items_buffer;
|
||||
}
|
||||
|
||||
LightClusterBuilder::LightClusterBuilder() {
|
||||
//initialize accumulators to something
|
||||
lights = (LightData *)memalloc(sizeof(LightData) * 1024);
|
||||
light_max = 1024;
|
||||
|
||||
refprobes = (OrientedBoxData *)memalloc(sizeof(OrientedBoxData) * 1024);
|
||||
refprobe_max = 1024;
|
||||
|
||||
decals = (OrientedBoxData *)memalloc(sizeof(OrientedBoxData) * 1024);
|
||||
decal_max = 1024;
|
||||
|
||||
items = (Item *)memalloc(sizeof(Item) * 1024);
|
||||
item_max = 1024;
|
||||
|
||||
sort_ids = (SortID *)memalloc(sizeof(SortID) * 1024);
|
||||
ids.resize(2014);
|
||||
items_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 1024);
|
||||
item_max = 1024;
|
||||
}
|
||||
LightClusterBuilder::~LightClusterBuilder() {
|
||||
|
||||
if (cluster_data.size()) {
|
||||
RD::get_singleton()->free(cluster_texture);
|
||||
}
|
||||
|
||||
if (lights) {
|
||||
memfree(lights);
|
||||
}
|
||||
if (refprobes) {
|
||||
memfree(refprobes);
|
||||
}
|
||||
if (decals) {
|
||||
memfree(decals);
|
||||
}
|
||||
if (items) {
|
||||
memfree(items);
|
||||
}
|
||||
if (sort_ids) {
|
||||
memfree(sort_ids);
|
||||
RD::get_singleton()->free(items_buffer);
|
||||
}
|
||||
}
|
||||
291
servers/rendering/rasterizer_rd/light_cluster_builder.h
Normal file
291
servers/rendering/rasterizer_rd/light_cluster_builder.h
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
/*************************************************************************/
|
||||
/* light_cluster_builder.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef LIGHT_CLUSTER_BUILDER_H
|
||||
#define LIGHT_CLUSTER_BUILDER_H
|
||||
|
||||
#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h"
|
||||
|
||||
class LightClusterBuilder {
|
||||
public:
|
||||
enum LightType {
|
||||
LIGHT_TYPE_OMNI,
|
||||
LIGHT_TYPE_SPOT
|
||||
};
|
||||
|
||||
enum ItemType {
|
||||
ITEM_TYPE_OMNI_LIGHT,
|
||||
ITEM_TYPE_SPOT_LIGHT,
|
||||
ITEM_TYPE_REFLECTION_PROBE,
|
||||
ITEM_TYPE_DECAL,
|
||||
ITEM_TYPE_MAX //should always be 4
|
||||
};
|
||||
|
||||
enum {
|
||||
COUNTER_SHIFT = 20, //one million total ids
|
||||
POINTER_MASK = (1 << COUNTER_SHIFT) - 1,
|
||||
COUNTER_MASK = 0xfff // 4096 items per cell
|
||||
};
|
||||
|
||||
private:
|
||||
struct LightData {
|
||||
float position[3];
|
||||
uint32_t type;
|
||||
float radius;
|
||||
float spot_aperture;
|
||||
uint32_t pad[2];
|
||||
};
|
||||
|
||||
uint32_t light_count = 0;
|
||||
uint32_t light_max = 0;
|
||||
LightData *lights = nullptr;
|
||||
|
||||
struct OrientedBoxData {
|
||||
float position[3];
|
||||
uint32_t pad;
|
||||
float x_axis[3];
|
||||
uint32_t pad2;
|
||||
float y_axis[3];
|
||||
uint32_t pad3;
|
||||
float z_axis[3];
|
||||
uint32_t pad4;
|
||||
};
|
||||
|
||||
uint32_t refprobe_count = 0;
|
||||
uint32_t refprobe_max = 0;
|
||||
OrientedBoxData *refprobes = nullptr;
|
||||
|
||||
uint32_t decal_count = 0;
|
||||
uint32_t decal_max = 0;
|
||||
OrientedBoxData *decals = nullptr;
|
||||
|
||||
struct Item {
|
||||
AABB aabb;
|
||||
ItemType type;
|
||||
uint32_t index;
|
||||
};
|
||||
|
||||
Item *items = nullptr;
|
||||
uint32_t item_count = 0;
|
||||
uint32_t item_max = 0;
|
||||
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
uint32_t depth = 0;
|
||||
|
||||
struct Cell {
|
||||
uint32_t item_pointers[ITEM_TYPE_MAX];
|
||||
};
|
||||
|
||||
Vector<uint8_t> cluster_data;
|
||||
RID cluster_texture;
|
||||
|
||||
struct SortID {
|
||||
uint32_t cell_index;
|
||||
uint32_t item_index;
|
||||
ItemType item_type;
|
||||
};
|
||||
|
||||
SortID *sort_ids = nullptr;
|
||||
Vector<uint32_t> ids;
|
||||
uint32_t sort_id_count = 0;
|
||||
uint32_t sort_id_max = 0;
|
||||
RID items_buffer;
|
||||
|
||||
Transform view_xform;
|
||||
CameraMatrix projection;
|
||||
float z_far = 0;
|
||||
float z_near = 0;
|
||||
|
||||
_FORCE_INLINE_ void _add_item(const AABB &p_aabb, ItemType p_type, uint32_t p_index) {
|
||||
if (unlikely(item_count == item_max)) {
|
||||
item_max = nearest_power_of_2_templated(item_max + 1);
|
||||
items = (Item *)memrealloc(items, sizeof(Item) * item_max);
|
||||
}
|
||||
|
||||
Item &item = items[item_count];
|
||||
item.aabb = p_aabb;
|
||||
item.index = p_index;
|
||||
item.type = p_type;
|
||||
item_count++;
|
||||
}
|
||||
|
||||
public:
|
||||
void begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection);
|
||||
|
||||
_FORCE_INLINE_ void add_light(LightType p_type, const Transform &p_transform, float p_radius, float p_spot_aperture) {
|
||||
if (unlikely(light_count == light_max)) {
|
||||
light_max = nearest_power_of_2_templated(light_max + 1);
|
||||
lights = (LightData *)memrealloc(lights, sizeof(LightData) * light_max);
|
||||
}
|
||||
|
||||
LightData &ld = lights[light_count];
|
||||
ld.type = p_type;
|
||||
ld.position[0] = p_transform.origin.x;
|
||||
ld.position[1] = p_transform.origin.y;
|
||||
ld.position[2] = p_transform.origin.z;
|
||||
ld.radius = p_radius;
|
||||
ld.spot_aperture = p_spot_aperture;
|
||||
|
||||
Transform xform = view_xform * p_transform;
|
||||
|
||||
ld.radius *= xform.basis.get_uniform_scale();
|
||||
|
||||
AABB aabb;
|
||||
|
||||
switch (p_type) {
|
||||
case LIGHT_TYPE_OMNI: {
|
||||
aabb.position = xform.origin;
|
||||
aabb.size = Vector3(ld.radius, ld.radius, ld.radius);
|
||||
aabb.position -= aabb.size;
|
||||
aabb.size *= 2.0;
|
||||
|
||||
_add_item(aabb, ITEM_TYPE_OMNI_LIGHT, light_count);
|
||||
} break;
|
||||
case LIGHT_TYPE_SPOT: {
|
||||
Vector3 v(0, 0, -1);
|
||||
v.rotated(Vector3(0, 1, 0), Math::deg2rad(ld.spot_aperture)); //rotate in x-z
|
||||
v.normalize();
|
||||
v *= ld.radius;
|
||||
v.y = v.x;
|
||||
|
||||
aabb.position = xform.origin;
|
||||
aabb.expand_to(xform.xform(v));
|
||||
aabb.expand_to(xform.xform(Vector3(-v.x, v.y, v.z)));
|
||||
aabb.expand_to(xform.xform(Vector3(-v.x, -v.y, v.z)));
|
||||
aabb.expand_to(xform.xform(Vector3(v.x, -v.y, v.z)));
|
||||
_add_item(aabb, ITEM_TYPE_SPOT_LIGHT, light_count);
|
||||
} break;
|
||||
}
|
||||
|
||||
light_count++;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void add_reflection_probe(const Transform &p_transform, const Vector3 &p_half_extents) {
|
||||
|
||||
if (unlikely(refprobe_count == refprobe_max)) {
|
||||
refprobe_max = nearest_power_of_2_templated(refprobe_max + 1);
|
||||
refprobes = (OrientedBoxData *)memrealloc(refprobes, sizeof(OrientedBoxData) * refprobe_max);
|
||||
}
|
||||
|
||||
OrientedBoxData &rp = refprobes[refprobe_count];
|
||||
Vector3 origin = p_transform.origin;
|
||||
rp.position[0] = origin.x;
|
||||
rp.position[1] = origin.y;
|
||||
rp.position[2] = origin.z;
|
||||
|
||||
Vector3 x_axis = p_transform.basis.get_axis(0) * p_half_extents.x;
|
||||
rp.x_axis[0] = x_axis.x;
|
||||
rp.x_axis[1] = x_axis.y;
|
||||
rp.x_axis[2] = x_axis.z;
|
||||
|
||||
Vector3 y_axis = p_transform.basis.get_axis(1) * p_half_extents.y;
|
||||
rp.y_axis[0] = y_axis.x;
|
||||
rp.y_axis[1] = y_axis.y;
|
||||
rp.y_axis[2] = y_axis.z;
|
||||
|
||||
Vector3 z_axis = p_transform.basis.get_axis(2) * p_half_extents.z;
|
||||
rp.z_axis[0] = z_axis.x;
|
||||
rp.z_axis[1] = z_axis.y;
|
||||
rp.z_axis[2] = z_axis.z;
|
||||
|
||||
AABB aabb;
|
||||
|
||||
aabb.position = origin + x_axis + y_axis + z_axis;
|
||||
aabb.expand_to(origin + x_axis + y_axis - z_axis);
|
||||
aabb.expand_to(origin + x_axis - y_axis + z_axis);
|
||||
aabb.expand_to(origin + x_axis - y_axis - z_axis);
|
||||
aabb.expand_to(origin - x_axis + y_axis + z_axis);
|
||||
aabb.expand_to(origin - x_axis + y_axis - z_axis);
|
||||
aabb.expand_to(origin - x_axis - y_axis + z_axis);
|
||||
aabb.expand_to(origin - x_axis - y_axis - z_axis);
|
||||
|
||||
_add_item(aabb, ITEM_TYPE_REFLECTION_PROBE, refprobe_count);
|
||||
|
||||
refprobe_count++;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void add_decal(const Transform &p_transform, const Vector2 &p_half_extents, float p_depth) {
|
||||
|
||||
if (unlikely(decal_count == decal_max)) {
|
||||
decal_max = nearest_power_of_2_templated(decal_max + 1);
|
||||
decals = (OrientedBoxData *)memrealloc(decals, sizeof(OrientedBoxData) * decal_max);
|
||||
}
|
||||
|
||||
OrientedBoxData &dc = decals[decal_count];
|
||||
|
||||
Vector3 z_axis = -p_transform.basis.get_axis(2) * p_depth * 0.5;
|
||||
dc.z_axis[0] = z_axis.x;
|
||||
dc.z_axis[1] = z_axis.y;
|
||||
dc.z_axis[2] = z_axis.z;
|
||||
|
||||
Vector3 origin = p_transform.origin - z_axis;
|
||||
dc.position[0] = origin.x;
|
||||
dc.position[1] = origin.y;
|
||||
dc.position[2] = origin.z;
|
||||
|
||||
Vector3 x_axis = p_transform.basis.get_axis(0) * p_half_extents.x;
|
||||
dc.x_axis[0] = x_axis.x;
|
||||
dc.x_axis[1] = x_axis.y;
|
||||
dc.x_axis[2] = x_axis.z;
|
||||
|
||||
Vector3 y_axis = p_transform.basis.get_axis(1) * p_half_extents.y;
|
||||
dc.y_axis[0] = y_axis.x;
|
||||
dc.y_axis[1] = y_axis.y;
|
||||
dc.y_axis[2] = y_axis.z;
|
||||
|
||||
AABB aabb;
|
||||
|
||||
aabb.position = origin + x_axis + y_axis + z_axis;
|
||||
aabb.expand_to(origin + x_axis + y_axis - z_axis);
|
||||
aabb.expand_to(origin + x_axis - y_axis + z_axis);
|
||||
aabb.expand_to(origin + x_axis - y_axis - z_axis);
|
||||
aabb.expand_to(origin - x_axis + y_axis + z_axis);
|
||||
aabb.expand_to(origin - x_axis + y_axis - z_axis);
|
||||
aabb.expand_to(origin - x_axis - y_axis + z_axis);
|
||||
aabb.expand_to(origin - x_axis - y_axis - z_axis);
|
||||
|
||||
_add_item(aabb, ITEM_TYPE_DECAL, decal_count);
|
||||
|
||||
decal_count++;
|
||||
}
|
||||
|
||||
void bake_cluster();
|
||||
|
||||
void setup(uint32_t p_width, uint32_t p_height, uint32_t p_depth);
|
||||
|
||||
RID get_cluster_texture() const;
|
||||
RID get_cluster_indices_buffer() const;
|
||||
|
||||
LightClusterBuilder();
|
||||
~LightClusterBuilder();
|
||||
};
|
||||
|
||||
#endif // LIGHT_CLUSTER_BUILDER_H
|
||||
2558
servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
Normal file
2558
servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp
Normal file
File diff suppressed because it is too large
Load diff
501
servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
Normal file
501
servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h
Normal file
|
|
@ -0,0 +1,501 @@
|
|||
/*************************************************************************/
|
||||
/* rasterizer_canvas_rd.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef RASTERIZER_CANVAS_RD_H
|
||||
#define RASTERIZER_CANVAS_RD_H
|
||||
|
||||
#include "servers/rendering/rasterizer.h"
|
||||
#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/shader_compiler_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/canvas.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl.gen.h"
|
||||
#include "servers/rendering/rendering_device.h"
|
||||
|
||||
class RasterizerCanvasRD : public RasterizerCanvas {
|
||||
|
||||
RasterizerStorageRD *storage;
|
||||
|
||||
enum ShaderVariant {
|
||||
SHADER_VARIANT_QUAD,
|
||||
SHADER_VARIANT_NINEPATCH,
|
||||
SHADER_VARIANT_PRIMITIVE,
|
||||
SHADER_VARIANT_PRIMITIVE_POINTS,
|
||||
SHADER_VARIANT_ATTRIBUTES,
|
||||
SHADER_VARIANT_ATTRIBUTES_POINTS,
|
||||
SHADER_VARIANT_QUAD_LIGHT,
|
||||
SHADER_VARIANT_NINEPATCH_LIGHT,
|
||||
SHADER_VARIANT_PRIMITIVE_LIGHT,
|
||||
SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT,
|
||||
SHADER_VARIANT_ATTRIBUTES_LIGHT,
|
||||
SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT,
|
||||
SHADER_VARIANT_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
FLAGS_INSTANCING_STRIDE_MASK = 0xF,
|
||||
FLAGS_INSTANCING_ENABLED = (1 << 4),
|
||||
FLAGS_INSTANCING_HAS_COLORS = (1 << 5),
|
||||
FLAGS_INSTANCING_COLOR_8BIT = (1 << 6),
|
||||
FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 7),
|
||||
FLAGS_INSTANCING_CUSTOM_DATA_8_BIT = (1 << 8),
|
||||
|
||||
FLAGS_CLIP_RECT_UV = (1 << 9),
|
||||
FLAGS_TRANSPOSE_RECT = (1 << 10),
|
||||
FLAGS_USING_LIGHT_MASK = (1 << 11),
|
||||
|
||||
FLAGS_NINEPACH_DRAW_CENTER = (1 << 12),
|
||||
FLAGS_USING_PARTICLES = (1 << 13),
|
||||
FLAGS_USE_PIXEL_SNAP = (1 << 14),
|
||||
|
||||
FLAGS_USE_SKELETON = (1 << 15),
|
||||
FLAGS_NINEPATCH_H_MODE_SHIFT = 16,
|
||||
FLAGS_NINEPATCH_V_MODE_SHIFT = 18,
|
||||
FLAGS_LIGHT_COUNT_SHIFT = 20,
|
||||
|
||||
FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 26),
|
||||
FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27)
|
||||
|
||||
};
|
||||
|
||||
enum {
|
||||
LIGHT_FLAGS_TEXTURE_MASK = 0xFFFF,
|
||||
LIGHT_FLAGS_BLEND_SHIFT = 16,
|
||||
LIGHT_FLAGS_BLEND_MASK = (3 << 16),
|
||||
LIGHT_FLAGS_BLEND_MODE_ADD = (0 << 16),
|
||||
LIGHT_FLAGS_BLEND_MODE_SUB = (1 << 16),
|
||||
LIGHT_FLAGS_BLEND_MODE_MIX = (2 << 16),
|
||||
LIGHT_FLAGS_BLEND_MODE_MASK = (3 << 16),
|
||||
LIGHT_FLAGS_HAS_SHADOW = (1 << 20),
|
||||
LIGHT_FLAGS_FILTER_SHIFT = 22
|
||||
|
||||
};
|
||||
|
||||
enum {
|
||||
MAX_RENDER_ITEMS = 256 * 1024,
|
||||
MAX_LIGHT_TEXTURES = 1024,
|
||||
DEFAULT_MAX_LIGHTS_PER_ITEM = 16,
|
||||
DEFAULT_MAX_LIGHTS_PER_RENDER = 256
|
||||
};
|
||||
|
||||
/****************/
|
||||
/**** SHADER ****/
|
||||
/****************/
|
||||
|
||||
enum PipelineVariant {
|
||||
PIPELINE_VARIANT_QUAD,
|
||||
PIPELINE_VARIANT_NINEPATCH,
|
||||
PIPELINE_VARIANT_PRIMITIVE_TRIANGLES,
|
||||
PIPELINE_VARIANT_PRIMITIVE_LINES,
|
||||
PIPELINE_VARIANT_PRIMITIVE_POINTS,
|
||||
PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES,
|
||||
PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP,
|
||||
PIPELINE_VARIANT_ATTRIBUTE_LINES,
|
||||
PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP,
|
||||
PIPELINE_VARIANT_ATTRIBUTE_POINTS,
|
||||
PIPELINE_VARIANT_MAX
|
||||
};
|
||||
enum PipelineLightMode {
|
||||
PIPELINE_LIGHT_MODE_DISABLED,
|
||||
PIPELINE_LIGHT_MODE_ENABLED,
|
||||
PIPELINE_LIGHT_MODE_MAX
|
||||
};
|
||||
|
||||
struct PipelineVariants {
|
||||
RenderPipelineVertexFormatCacheRD variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX];
|
||||
};
|
||||
|
||||
struct {
|
||||
CanvasShaderRD canvas_shader;
|
||||
RID default_version;
|
||||
RID default_version_rd_shader;
|
||||
RID default_version_rd_shader_light;
|
||||
RID quad_index_buffer;
|
||||
RID quad_index_array;
|
||||
PipelineVariants pipeline_variants;
|
||||
|
||||
// default_skeleton uniform set
|
||||
RID default_skeleton_uniform_buffer;
|
||||
RID default_skeleton_texture_buffer;
|
||||
|
||||
ShaderCompilerRD compiler;
|
||||
} shader;
|
||||
|
||||
struct ShaderData : public RasterizerStorageRD::ShaderData {
|
||||
|
||||
enum BlendMode { //used internally
|
||||
BLEND_MODE_MIX,
|
||||
BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB,
|
||||
BLEND_MODE_MUL,
|
||||
BLEND_MODE_PMALPHA,
|
||||
BLEND_MODE_DISABLED,
|
||||
};
|
||||
|
||||
enum LightMode {
|
||||
LIGHT_MODE_NORMAL,
|
||||
LIGHT_MODE_UNSHADED,
|
||||
LIGHT_MODE_LIGHT_ONLY
|
||||
};
|
||||
|
||||
bool valid;
|
||||
RID version;
|
||||
PipelineVariants pipeline_variants;
|
||||
String path;
|
||||
|
||||
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
|
||||
Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
|
||||
|
||||
Vector<uint32_t> ubo_offsets;
|
||||
uint32_t ubo_size;
|
||||
|
||||
String code;
|
||||
Map<StringName, RID> default_texture_params;
|
||||
|
||||
bool uses_screen_texture;
|
||||
bool uses_material_samplers;
|
||||
|
||||
virtual void set_code(const String &p_Code);
|
||||
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
|
||||
virtual void get_param_list(List<PropertyInfo> *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;
|
||||
ShaderData();
|
||||
virtual ~ShaderData();
|
||||
};
|
||||
|
||||
RasterizerStorageRD::ShaderData *_create_shader_func();
|
||||
static RasterizerStorageRD::ShaderData *_create_shader_funcs() {
|
||||
return static_cast<RasterizerCanvasRD *>(singleton)->_create_shader_func();
|
||||
}
|
||||
|
||||
struct MaterialData : public RasterizerStorageRD::MaterialData {
|
||||
uint64_t last_frame;
|
||||
ShaderData *shader_data;
|
||||
RID uniform_buffer;
|
||||
RID uniform_set;
|
||||
Vector<RID> texture_cache;
|
||||
Vector<uint8_t> ubo_data;
|
||||
|
||||
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 ~MaterialData();
|
||||
};
|
||||
|
||||
RasterizerStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
|
||||
static RasterizerStorageRD::MaterialData *_create_material_funcs(RasterizerStorageRD::ShaderData *p_shader) {
|
||||
return static_cast<RasterizerCanvasRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/**** TEXTURE BINDINGS ****/
|
||||
/**************************/
|
||||
|
||||
// bindings used to render commands,
|
||||
// cached for performance.
|
||||
|
||||
struct TextureBindingKey {
|
||||
RID texture;
|
||||
RID normalmap;
|
||||
RID specular;
|
||||
RID multimesh;
|
||||
RS::CanvasItemTextureFilter texture_filter;
|
||||
RS::CanvasItemTextureRepeat texture_repeat;
|
||||
bool operator==(const TextureBindingKey &p_key) const {
|
||||
return texture == p_key.texture && normalmap == p_key.normalmap && specular == p_key.specular && multimesh == p_key.specular && texture_filter == p_key.texture_filter && texture_repeat == p_key.texture_repeat;
|
||||
}
|
||||
};
|
||||
|
||||
struct TextureBindingKeyHasher {
|
||||
static _FORCE_INLINE_ uint32_t hash(const TextureBindingKey &p_key) {
|
||||
uint32_t hash = hash_djb2_one_64(p_key.texture.get_id());
|
||||
hash = hash_djb2_one_64(p_key.normalmap.get_id(), hash);
|
||||
hash = hash_djb2_one_64(p_key.specular.get_id(), hash);
|
||||
hash = hash_djb2_one_64(p_key.multimesh.get_id(), hash);
|
||||
hash = hash_djb2_one_32(uint32_t(p_key.texture_filter) << 16 | uint32_t(p_key.texture_repeat), hash);
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
struct TextureBinding {
|
||||
TextureBindingID id;
|
||||
TextureBindingKey key;
|
||||
SelfList<TextureBinding> to_dispose;
|
||||
uint32_t reference_count;
|
||||
RID uniform_set;
|
||||
TextureBinding() :
|
||||
to_dispose(this) {
|
||||
reference_count = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct {
|
||||
SelfList<TextureBinding>::List to_dispose_list;
|
||||
|
||||
TextureBindingID id_generator;
|
||||
HashMap<TextureBindingKey, TextureBindingID, TextureBindingKeyHasher> texture_key_bindings;
|
||||
HashMap<TextureBindingID, TextureBinding *> texture_bindings;
|
||||
|
||||
TextureBindingID default_empty;
|
||||
} bindings;
|
||||
|
||||
RID _create_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat, RID p_multimesh);
|
||||
void _dispose_bindings();
|
||||
|
||||
struct {
|
||||
RS::CanvasItemTextureFilter default_filter;
|
||||
RS::CanvasItemTextureRepeat default_repeat;
|
||||
} default_samplers;
|
||||
|
||||
/******************/
|
||||
/**** POLYGONS ****/
|
||||
/******************/
|
||||
|
||||
struct PolygonBuffers {
|
||||
RD::VertexFormatID vertex_format_id;
|
||||
RID vertex_buffer;
|
||||
RID vertex_array;
|
||||
RID index_buffer;
|
||||
RID indices;
|
||||
};
|
||||
|
||||
struct {
|
||||
HashMap<PolygonID, PolygonBuffers> polygons;
|
||||
PolygonID last_id;
|
||||
} polygon_buffers;
|
||||
|
||||
/********************/
|
||||
/**** PRIMITIVES ****/
|
||||
/********************/
|
||||
|
||||
struct {
|
||||
RID index_array[4];
|
||||
} primitive_arrays;
|
||||
|
||||
/*******************/
|
||||
/**** MATERIALS ****/
|
||||
/*******************/
|
||||
|
||||
/******************/
|
||||
/**** LIGHTING ****/
|
||||
/******************/
|
||||
|
||||
struct CanvasLight {
|
||||
|
||||
RID texture;
|
||||
struct {
|
||||
int size;
|
||||
RID texture;
|
||||
RID depth;
|
||||
RID fb;
|
||||
} shadow;
|
||||
};
|
||||
|
||||
RID_Owner<CanvasLight> canvas_light_owner;
|
||||
|
||||
struct ShadowRenderPushConstant {
|
||||
float projection[16];
|
||||
float modelview[8];
|
||||
float direction[2];
|
||||
float pad[2];
|
||||
};
|
||||
|
||||
struct OccluderPolygon {
|
||||
|
||||
RS::CanvasOccluderPolygonCullMode cull_mode;
|
||||
int point_count;
|
||||
RID vertex_buffer;
|
||||
RID vertex_array;
|
||||
RID index_buffer;
|
||||
RID index_array;
|
||||
};
|
||||
|
||||
struct LightUniform {
|
||||
float matrix[8]; //light to texture coordinate matrix
|
||||
float shadow_matrix[8]; //light to shadow coordinate matrix
|
||||
float color[4];
|
||||
float shadow_color[4];
|
||||
float position[2];
|
||||
uint32_t flags; //index to light texture
|
||||
float height;
|
||||
float shadow_pixel_size;
|
||||
float pad[3];
|
||||
};
|
||||
|
||||
RID_Owner<OccluderPolygon> occluder_polygon_owner;
|
||||
|
||||
struct {
|
||||
CanvasOcclusionShaderRD shader;
|
||||
RID shader_version;
|
||||
RID render_pipelines[3];
|
||||
RD::VertexFormatID vertex_format;
|
||||
RD::FramebufferFormatID framebuffer_format;
|
||||
} shadow_render;
|
||||
|
||||
/***************/
|
||||
/**** STATE ****/
|
||||
/***************/
|
||||
|
||||
//state that does not vary across rendering all items
|
||||
|
||||
struct ItemStateData : public Item::CustomData {
|
||||
|
||||
struct LightCache {
|
||||
uint64_t light_version;
|
||||
Light *light;
|
||||
};
|
||||
|
||||
LightCache light_cache[DEFAULT_MAX_LIGHTS_PER_ITEM];
|
||||
uint32_t light_cache_count;
|
||||
RID state_uniform_set_with_light;
|
||||
RID state_uniform_set;
|
||||
ItemStateData() {
|
||||
|
||||
for (int i = 0; i < DEFAULT_MAX_LIGHTS_PER_ITEM; i++) {
|
||||
light_cache[i].light_version = 0;
|
||||
light_cache[i].light = NULL;
|
||||
}
|
||||
light_cache_count = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
~ItemStateData() {
|
||||
if (state_uniform_set_with_light.is_valid() && RD::get_singleton()->uniform_set_is_valid(state_uniform_set_with_light)) {
|
||||
RD::get_singleton()->free(state_uniform_set_with_light);
|
||||
}
|
||||
if (state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state_uniform_set)) {
|
||||
RD::get_singleton()->free(state_uniform_set);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct State {
|
||||
|
||||
//state buffer
|
||||
struct Buffer {
|
||||
float canvas_transform[16];
|
||||
float screen_transform[16];
|
||||
float canvas_normal_transform[16];
|
||||
float canvas_modulate[4];
|
||||
float screen_pixel_size[2];
|
||||
float time;
|
||||
float pad;
|
||||
|
||||
//uint32_t light_count;
|
||||
//uint32_t pad[3];
|
||||
};
|
||||
|
||||
LightUniform *light_uniforms;
|
||||
|
||||
RID lights_uniform_buffer;
|
||||
RID canvas_state_buffer;
|
||||
RID shadow_sampler;
|
||||
|
||||
uint32_t max_lights_per_render;
|
||||
uint32_t max_lights_per_item;
|
||||
|
||||
double time;
|
||||
} state;
|
||||
|
||||
struct PushConstant {
|
||||
float world[6];
|
||||
uint32_t flags;
|
||||
uint32_t specular_shininess;
|
||||
union {
|
||||
//rect
|
||||
struct {
|
||||
float modulation[4];
|
||||
float ninepatch_margins[4];
|
||||
float dst_rect[4];
|
||||
float src_rect[4];
|
||||
float pad[2];
|
||||
};
|
||||
//primitive
|
||||
struct {
|
||||
float points[6]; // vec2 points[3]
|
||||
float uvs[6]; // vec2 points[3]
|
||||
uint32_t colors[6]; // colors encoded as half
|
||||
};
|
||||
};
|
||||
float color_texture_pixel_size[2];
|
||||
uint32_t lights[4];
|
||||
};
|
||||
|
||||
struct SkeletonUniform {
|
||||
float skeleton_transform[16];
|
||||
float skeleton_inverse[16];
|
||||
};
|
||||
|
||||
Item *items[MAX_RENDER_ITEMS];
|
||||
|
||||
Size2i _bind_texture_binding(TextureBindingID p_binding, RenderingDevice::DrawListID p_draw_list, uint32_t &flags);
|
||||
void _render_item(RenderingDevice::DrawListID p_draw_list, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants);
|
||||
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, RID p_screen_uniform_set);
|
||||
|
||||
_FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4);
|
||||
_FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3);
|
||||
|
||||
_FORCE_INLINE_ void _update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4);
|
||||
_FORCE_INLINE_ void _update_transform_to_mat4(const Transform &p_transform, float *p_mat4);
|
||||
|
||||
_FORCE_INLINE_ void _update_specular_shininess(const Color &p_transform, uint32_t *r_ss);
|
||||
|
||||
public:
|
||||
TextureBindingID request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat, RID p_multimesh);
|
||||
void free_texture_binding(TextureBindingID p_binding);
|
||||
|
||||
PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>());
|
||||
void free_polygon(PolygonID p_polygon);
|
||||
|
||||
RID light_create();
|
||||
void light_set_texture(RID p_rid, RID p_texture);
|
||||
void light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution);
|
||||
void light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders);
|
||||
|
||||
RID occluder_polygon_create();
|
||||
void occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector<Vector2> &p_lines);
|
||||
void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode);
|
||||
|
||||
void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform);
|
||||
|
||||
void canvas_debug_viewport_shadows(Light *p_lights_with_shadow){};
|
||||
|
||||
void draw_window_margins(int *p_margins, RID *p_margin_textures) {}
|
||||
|
||||
void set_time(double p_time);
|
||||
void update();
|
||||
bool free(RID p_rid);
|
||||
RasterizerCanvasRD(RasterizerStorageRD *p_storage);
|
||||
~RasterizerCanvasRD();
|
||||
};
|
||||
|
||||
#endif // RASTERIZER_CANVAS_RD_H
|
||||
1092
servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
Normal file
1092
servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp
Normal file
File diff suppressed because it is too large
Load diff
457
servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
Normal file
457
servers/rendering/rasterizer_rd/rasterizer_effects_rd.h
Normal file
|
|
@ -0,0 +1,457 @@
|
|||
/*************************************************************************/
|
||||
/* rasterizer_effects_rd.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef RASTERIZER_EFFECTS_RD_H
|
||||
#define RASTERIZER_EFFECTS_RD_H
|
||||
|
||||
#include "core/math/camera_matrix.h"
|
||||
#include "servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/blur.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/copy.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/ssao.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl.gen.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/tonemap.glsl.gen.h"
|
||||
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
class RasterizerEffectsRD {
|
||||
|
||||
enum BlurMode {
|
||||
BLUR_MODE_GAUSSIAN_BLUR,
|
||||
BLUR_MODE_GAUSSIAN_GLOW,
|
||||
BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE,
|
||||
BLUR_MODE_DOF_NEAR_LOW,
|
||||
BLUR_MODE_DOF_NEAR_MEDIUM,
|
||||
BLUR_MODE_DOF_NEAR_HIGH,
|
||||
BLUR_MODE_DOF_NEAR_MERGE_LOW,
|
||||
BLUR_MODE_DOF_NEAR_MERGE_MEDIUM,
|
||||
BLUR_MODE_DOF_NEAR_MERGE_HIGH,
|
||||
BLUR_MODE_DOF_FAR_LOW,
|
||||
BLUR_MODE_DOF_FAR_MEDIUM,
|
||||
BLUR_MODE_DOF_FAR_HIGH,
|
||||
BLUR_MODE_SSAO_MERGE,
|
||||
BLUR_MODE_SIMPLY_COPY,
|
||||
BLUR_MODE_MIPMAP,
|
||||
BLUR_MODE_MAX,
|
||||
|
||||
};
|
||||
|
||||
enum {
|
||||
BLUR_FLAG_HORIZONTAL = (1 << 0),
|
||||
BLUR_FLAG_USE_BLUR_SECTION = (1 << 1),
|
||||
BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2),
|
||||
BLUR_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3),
|
||||
BLUR_FLAG_GLOW_FIRST_PASS = (1 << 4),
|
||||
BLUR_FLAG_FLIP_Y = (1 << 5),
|
||||
BLUR_COPY_FORCE_LUMINANCE = (1 << 6)
|
||||
};
|
||||
|
||||
struct BlurPushConstant {
|
||||
float section[4];
|
||||
float pixel_size[2];
|
||||
uint32_t flags;
|
||||
uint32_t pad;
|
||||
//glow
|
||||
float glow_strength;
|
||||
float glow_bloom;
|
||||
float glow_hdr_threshold;
|
||||
float glow_hdr_scale;
|
||||
float glow_exposure;
|
||||
float glow_white;
|
||||
float glow_luminance_cap;
|
||||
float glow_auto_exposure_grey;
|
||||
//dof
|
||||
float dof_begin;
|
||||
float dof_end;
|
||||
float dof_radius;
|
||||
float dof_pad;
|
||||
|
||||
float dof_dir[2];
|
||||
float camera_z_far;
|
||||
float camera_z_near;
|
||||
|
||||
float ssao_color[4];
|
||||
};
|
||||
|
||||
struct Blur {
|
||||
BlurPushConstant push_constant;
|
||||
BlurShaderRD shader;
|
||||
RID shader_version;
|
||||
RenderPipelineVertexFormatCacheRD pipelines[BLUR_MODE_MAX];
|
||||
|
||||
} blur;
|
||||
|
||||
struct CubemapRoughnessPushConstant {
|
||||
uint32_t face_id;
|
||||
uint32_t sample_count;
|
||||
float roughness;
|
||||
uint32_t use_direct_write;
|
||||
float face_size;
|
||||
float pad[3];
|
||||
};
|
||||
|
||||
struct CubemapRoughness {
|
||||
|
||||
CubemapRoughnessPushConstant push_constant;
|
||||
CubemapRoughnessShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipeline;
|
||||
} roughness;
|
||||
|
||||
enum TonemapMode {
|
||||
TONEMAP_MODE_NORMAL,
|
||||
TONEMAP_MODE_BICUBIC_GLOW_FILTER,
|
||||
TONEMAP_MODE_MAX
|
||||
};
|
||||
|
||||
struct TonemapPushConstant {
|
||||
float bcs[3];
|
||||
uint32_t use_bcs;
|
||||
|
||||
uint32_t use_glow;
|
||||
uint32_t use_auto_exposure;
|
||||
uint32_t use_color_correction;
|
||||
uint32_t tonemapper;
|
||||
|
||||
uint32_t glow_texture_size[2];
|
||||
|
||||
float glow_intensity;
|
||||
uint32_t glow_level_flags;
|
||||
uint32_t glow_mode;
|
||||
|
||||
float exposure;
|
||||
float white;
|
||||
float auto_exposure_grey;
|
||||
};
|
||||
|
||||
struct Tonemap {
|
||||
|
||||
TonemapPushConstant push_constant;
|
||||
TonemapShaderRD shader;
|
||||
RID shader_version;
|
||||
RenderPipelineVertexFormatCacheRD pipelines[TONEMAP_MODE_MAX];
|
||||
} tonemap;
|
||||
|
||||
enum LuminanceReduceMode {
|
||||
LUMINANCE_REDUCE_READ,
|
||||
LUMINANCE_REDUCE,
|
||||
LUMINANCE_REDUCE_WRITE,
|
||||
LUMINANCE_REDUCE_MAX
|
||||
};
|
||||
|
||||
struct LuminanceReducePushConstant {
|
||||
int32_t source_size[2];
|
||||
float max_luminance;
|
||||
float min_luminance;
|
||||
float exposure_adjust;
|
||||
float pad[3];
|
||||
};
|
||||
|
||||
struct LuminanceReduce {
|
||||
|
||||
LuminanceReducePushConstant push_constant;
|
||||
LuminanceReduceShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipelines[LUMINANCE_REDUCE_MAX];
|
||||
} luminance_reduce;
|
||||
|
||||
struct CopyToDPPushConstant {
|
||||
float bias;
|
||||
float z_far;
|
||||
float z_near;
|
||||
uint32_t z_flip;
|
||||
};
|
||||
|
||||
enum CopyMode {
|
||||
COPY_MODE_CUBE_TO_DP,
|
||||
COPY_MODE_MAX
|
||||
};
|
||||
|
||||
struct Copy {
|
||||
|
||||
CopyShaderRD shader;
|
||||
RID shader_version;
|
||||
RenderPipelineVertexFormatCacheRD pipelines[COPY_MODE_MAX];
|
||||
} copy;
|
||||
|
||||
struct BokehPushConstant {
|
||||
uint32_t size[2];
|
||||
float z_far;
|
||||
float z_near;
|
||||
|
||||
uint32_t orthogonal;
|
||||
float blur_size;
|
||||
float blur_scale;
|
||||
uint32_t steps;
|
||||
|
||||
uint32_t blur_near_active;
|
||||
float blur_near_begin;
|
||||
float blur_near_end;
|
||||
uint32_t blur_far_active;
|
||||
|
||||
float blur_far_begin;
|
||||
float blur_far_end;
|
||||
uint32_t second_pass;
|
||||
uint32_t half_size;
|
||||
|
||||
uint32_t use_jitter;
|
||||
float jitter_seed;
|
||||
uint32_t pad[2];
|
||||
};
|
||||
|
||||
enum BokehMode {
|
||||
BOKEH_GEN_BLUR_SIZE,
|
||||
BOKEH_GEN_BOKEH_BOX,
|
||||
BOKEH_GEN_BOKEH_HEXAGONAL,
|
||||
BOKEH_GEN_BOKEH_CIRCULAR,
|
||||
BOKEH_COMPOSITE,
|
||||
BOKEH_MAX
|
||||
};
|
||||
|
||||
struct Bokeh {
|
||||
|
||||
BokehPushConstant push_constant;
|
||||
BokehDofShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipelines[BOKEH_MAX];
|
||||
} bokeh;
|
||||
|
||||
enum SSAOMode {
|
||||
SSAO_MINIFY_FIRST,
|
||||
SSAO_MINIFY_MIPMAP,
|
||||
SSAO_GATHER_LOW,
|
||||
SSAO_GATHER_MEDIUM,
|
||||
SSAO_GATHER_HIGH,
|
||||
SSAO_GATHER_ULTRA,
|
||||
SSAO_GATHER_LOW_HALF,
|
||||
SSAO_GATHER_MEDIUM_HALF,
|
||||
SSAO_GATHER_HIGH_HALF,
|
||||
SSAO_GATHER_ULTRA_HALF,
|
||||
SSAO_BLUR_PASS,
|
||||
SSAO_BLUR_PASS_HALF,
|
||||
SSAO_BLUR_UPSCALE,
|
||||
SSAO_MAX
|
||||
};
|
||||
|
||||
struct SSAOMinifyPushConstant {
|
||||
float pixel_size[2];
|
||||
float z_far;
|
||||
float z_near;
|
||||
int32_t source_size[2];
|
||||
uint32_t orthogonal;
|
||||
uint32_t pad;
|
||||
};
|
||||
|
||||
struct SSAOGatherPushConstant {
|
||||
int32_t screen_size[2];
|
||||
float z_far;
|
||||
float z_near;
|
||||
|
||||
uint32_t orthogonal;
|
||||
float intensity_div_r6;
|
||||
float radius;
|
||||
float bias;
|
||||
|
||||
float proj_info[4];
|
||||
float pixel_size[2];
|
||||
float proj_scale;
|
||||
uint32_t pad;
|
||||
};
|
||||
|
||||
struct SSAOBlurPushConstant {
|
||||
float edge_sharpness;
|
||||
int32_t filter_scale;
|
||||
float z_far;
|
||||
float z_near;
|
||||
uint32_t orthogonal;
|
||||
uint32_t pad[3];
|
||||
int32_t axis[2];
|
||||
int32_t screen_size[2];
|
||||
};
|
||||
|
||||
struct SSAO {
|
||||
|
||||
SSAOMinifyPushConstant minify_push_constant;
|
||||
SsaoMinifyShaderRD minify_shader;
|
||||
RID minify_shader_version;
|
||||
|
||||
SSAOGatherPushConstant gather_push_constant;
|
||||
SsaoShaderRD gather_shader;
|
||||
RID gather_shader_version;
|
||||
|
||||
SSAOBlurPushConstant blur_push_constant;
|
||||
SsaoBlurShaderRD blur_shader;
|
||||
RID blur_shader_version;
|
||||
|
||||
RID pipelines[SSAO_MAX];
|
||||
} ssao;
|
||||
|
||||
struct RoughnessLimiterPushConstant {
|
||||
int32_t screen_size[2];
|
||||
float curve;
|
||||
uint32_t pad;
|
||||
};
|
||||
|
||||
struct RoughnessLimiter {
|
||||
|
||||
RoughnessLimiterPushConstant push_constant;
|
||||
RoughnessLimiterShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipeline;
|
||||
|
||||
} roughness_limiter;
|
||||
|
||||
struct CubemapDownsamplerPushConstant {
|
||||
uint32_t face_size;
|
||||
float pad[3];
|
||||
};
|
||||
|
||||
struct CubemapDownsampler {
|
||||
|
||||
CubemapDownsamplerPushConstant push_constant;
|
||||
CubemapDownsamplerShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipeline;
|
||||
|
||||
} cubemap_downsampler;
|
||||
|
||||
enum CubemapFilterMode {
|
||||
FILTER_MODE_HIGH_QUALITY,
|
||||
FILTER_MODE_LOW_QUALITY,
|
||||
FILTER_MODE_HIGH_QUALITY_ARRAY,
|
||||
FILTER_MODE_LOW_QUALITY_ARRAY,
|
||||
FILTER_MODE_MAX,
|
||||
};
|
||||
|
||||
struct CubemapFilter {
|
||||
|
||||
CubemapFilterShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipelines[FILTER_MODE_MAX];
|
||||
RID uniform_set;
|
||||
RID image_uniform_set;
|
||||
RID coefficient_buffer;
|
||||
bool use_high_quality;
|
||||
|
||||
} filter;
|
||||
|
||||
struct SkyPushConstant {
|
||||
float orientation[12];
|
||||
float proj[4];
|
||||
float position[3];
|
||||
float multiplier;
|
||||
float time;
|
||||
float pad[3];
|
||||
};
|
||||
|
||||
RID default_sampler;
|
||||
RID default_mipmap_sampler;
|
||||
RID index_buffer;
|
||||
RID index_array;
|
||||
|
||||
Map<RID, RID> texture_to_uniform_set_cache;
|
||||
|
||||
Map<RID, RID> image_to_uniform_set_cache;
|
||||
Map<RID, RID> texture_to_compute_uniform_set_cache;
|
||||
|
||||
RID _get_uniform_set_from_image(RID p_texture);
|
||||
RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
|
||||
RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
|
||||
|
||||
public:
|
||||
//TODO must re-do most of the shaders in compute
|
||||
|
||||
void region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region);
|
||||
void copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false, bool p_force_luminance = false);
|
||||
void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region);
|
||||
void gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
|
||||
|
||||
void cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
|
||||
void make_mipmap(RID p_source_rd_texture, RID p_framebuffer_half, const Vector2 &p_pixel_size);
|
||||
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip);
|
||||
void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
|
||||
void bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_bokeh_texture1, RID p_bokeh_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
|
||||
|
||||
struct TonemapSettings {
|
||||
|
||||
bool use_glow = false;
|
||||
enum GlowMode {
|
||||
GLOW_MODE_ADD,
|
||||
GLOW_MODE_SCREEN,
|
||||
GLOW_MODE_SOFTLIGHT,
|
||||
GLOW_MODE_REPLACE,
|
||||
GLOW_MODE_MIX
|
||||
};
|
||||
|
||||
GlowMode glow_mode = GLOW_MODE_ADD;
|
||||
float glow_intensity = 1.0;
|
||||
uint32_t glow_level_flags = 0;
|
||||
Vector2i glow_texture_size;
|
||||
bool glow_use_bicubic_upscale = false;
|
||||
RID glow_texture;
|
||||
|
||||
RS::EnvironmentToneMapper tonemap_mode = RS::ENV_TONE_MAPPER_LINEAR;
|
||||
float exposure = 1.0;
|
||||
float white = 1.0;
|
||||
|
||||
bool use_auto_exposure = false;
|
||||
float auto_exposure_grey = 0.5;
|
||||
RID exposure_texture;
|
||||
|
||||
bool use_bcs = false;
|
||||
float brightness = 1.0;
|
||||
float contrast = 1.0;
|
||||
float saturation = 1.0;
|
||||
|
||||
bool use_color_correction = false;
|
||||
RID color_correction_texture;
|
||||
};
|
||||
|
||||
void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings);
|
||||
|
||||
void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, const Size2i &p_depth_buffer_size, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao1, bool p_half_size, RID p_ao2, RID p_upscale_buffer, float p_intensity, float p_radius, float p_bias, const CameraMatrix &p_projection, RS::EnvironmentSSAOQuality p_quality, RS::EnvironmentSSAOBlur p_blur, float p_edge_sharpness);
|
||||
|
||||
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
|
||||
void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
|
||||
void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array);
|
||||
void render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_lights, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position);
|
||||
|
||||
RasterizerEffectsRD();
|
||||
~RasterizerEffectsRD();
|
||||
};
|
||||
|
||||
#endif // !RASTERIZER_EFFECTS_RD_H
|
||||
177
servers/rendering/rasterizer_rd/rasterizer_rd.cpp
Normal file
177
servers/rendering/rasterizer_rd/rasterizer_rd.cpp
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/*************************************************************************/
|
||||
/* rasterizer_rd.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "rasterizer_rd.h"
|
||||
|
||||
void RasterizerRD::prepare_for_blitting_render_targets() {
|
||||
RD::get_singleton()->prepare_screen_for_drawing();
|
||||
}
|
||||
|
||||
void RasterizerRD::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) {
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin_for_screen(p_screen);
|
||||
|
||||
for (int i = 0; i < p_amount; i++) {
|
||||
RID texture = storage->render_target_get_texture(p_render_targets[i].render_target);
|
||||
ERR_CONTINUE(texture.is_null());
|
||||
RID rd_texture = storage->texture_get_rd_texture(texture);
|
||||
ERR_CONTINUE(rd_texture.is_null());
|
||||
if (!render_target_descriptors.has(rd_texture) || !RD::get_singleton()->uniform_set_is_valid(render_target_descriptors[rd_texture])) {
|
||||
Vector<RD::Uniform> uniforms;
|
||||
RD::Uniform u;
|
||||
u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
|
||||
u.binding = 0;
|
||||
u.ids.push_back(copy_viewports_sampler);
|
||||
u.ids.push_back(rd_texture);
|
||||
uniforms.push_back(u);
|
||||
RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, copy_viewports_rd_shader, 0);
|
||||
|
||||
render_target_descriptors[rd_texture] = uniform_set;
|
||||
}
|
||||
|
||||
Size2 screen_size(RD::get_singleton()->screen_get_width(p_screen), RD::get_singleton()->screen_get_height(p_screen));
|
||||
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_viewports_rd_pipeline);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, copy_viewports_rd_array);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0);
|
||||
|
||||
float push_constant[4] = {
|
||||
p_render_targets[i].rect.position.x / screen_size.width,
|
||||
p_render_targets[i].rect.position.y / screen_size.height,
|
||||
p_render_targets[i].rect.size.width / screen_size.width,
|
||||
p_render_targets[i].rect.size.height / screen_size.height,
|
||||
};
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, push_constant, 4 * sizeof(float));
|
||||
RD::get_singleton()->draw_list_draw(draw_list, true);
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
void RasterizerRD::begin_frame(double frame_step) {
|
||||
frame++;
|
||||
time += frame_step;
|
||||
canvas->set_time(time);
|
||||
scene->set_time(time, frame_step);
|
||||
}
|
||||
|
||||
void RasterizerRD::end_frame(bool p_swap_buffers) {
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#warning TODO: likely passa bool to swap buffers to avoid display?
|
||||
#endif
|
||||
RD::get_singleton()->swap_buffers(); //probably should pass some bool to avoid display?
|
||||
}
|
||||
|
||||
void RasterizerRD::initialize() {
|
||||
|
||||
{ //create framebuffer copy shader
|
||||
RenderingDevice::ShaderStageData vert;
|
||||
vert.shader_stage = RenderingDevice::SHADER_STAGE_VERTEX;
|
||||
vert.spir_v = RenderingDevice::get_singleton()->shader_compile_from_source(RenderingDevice::SHADER_STAGE_VERTEX,
|
||||
"#version 450\n"
|
||||
"layout(push_constant, binding = 0, std140) uniform Pos { vec4 dst_rect; } pos;\n"
|
||||
"layout(location =0) out vec2 uv;\n"
|
||||
"void main() { \n"
|
||||
" vec2 base_arr[4] = vec2[](vec2(0.0,0.0),vec2(0.0,1.0),vec2(1.0,1.0),vec2(1.0,0.0));\n"
|
||||
" uv = base_arr[gl_VertexIndex];\n"
|
||||
" vec2 vtx = pos.dst_rect.xy+uv*pos.dst_rect.zw;\n"
|
||||
" gl_Position = vec4(vtx * 2.0 - 1.0,0.0,1.0);\n"
|
||||
"}\n");
|
||||
|
||||
RenderingDevice::ShaderStageData frag;
|
||||
frag.shader_stage = RenderingDevice::SHADER_STAGE_FRAGMENT;
|
||||
frag.spir_v = RenderingDevice::get_singleton()->shader_compile_from_source(RenderingDevice::SHADER_STAGE_FRAGMENT,
|
||||
"#version 450\n"
|
||||
"layout (location = 0) in vec2 uv;\n"
|
||||
"layout (location = 0) out vec4 color;\n"
|
||||
"layout (binding = 0) uniform sampler2D src_rt;\n"
|
||||
"void main() { color=texture(src_rt,uv); }\n");
|
||||
|
||||
Vector<RenderingDevice::ShaderStageData> source;
|
||||
source.push_back(vert);
|
||||
source.push_back(frag);
|
||||
String error;
|
||||
copy_viewports_rd_shader = RD::get_singleton()->shader_create(source);
|
||||
if (!copy_viewports_rd_shader.is_valid()) {
|
||||
print_line("Failed compilation: " + error);
|
||||
}
|
||||
}
|
||||
|
||||
{ //create index array for copy shader
|
||||
Vector<uint8_t> pv;
|
||||
pv.resize(6 * 4);
|
||||
{
|
||||
uint8_t *w = pv.ptrw();
|
||||
int *p32 = (int *)w;
|
||||
p32[0] = 0;
|
||||
p32[1] = 1;
|
||||
p32[2] = 2;
|
||||
p32[3] = 0;
|
||||
p32[4] = 2;
|
||||
p32[5] = 3;
|
||||
}
|
||||
copy_viewports_rd_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv);
|
||||
copy_viewports_rd_array = RD::get_singleton()->index_array_create(copy_viewports_rd_index_buffer, 0, 6);
|
||||
}
|
||||
|
||||
{ //pipeline
|
||||
copy_viewports_rd_pipeline = RD::get_singleton()->render_pipeline_create(copy_viewports_rd_shader, RD::get_singleton()->screen_get_framebuffer_format(), RD::INVALID_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RenderingDevice::PipelineColorBlendState::create_disabled(), 0);
|
||||
}
|
||||
{ // sampler
|
||||
copy_viewports_sampler = RD::get_singleton()->sampler_create(RD::SamplerState());
|
||||
}
|
||||
}
|
||||
|
||||
ThreadWorkPool RasterizerRD::thread_work_pool;
|
||||
uint32_t RasterizerRD::frame = 1;
|
||||
|
||||
void RasterizerRD::finalize() {
|
||||
|
||||
thread_work_pool.finish();
|
||||
|
||||
memdelete(scene);
|
||||
memdelete(canvas);
|
||||
memdelete(storage);
|
||||
|
||||
//only need to erase these, the rest are erased by cascade
|
||||
RD::get_singleton()->free(copy_viewports_rd_index_buffer);
|
||||
RD::get_singleton()->free(copy_viewports_rd_shader);
|
||||
RD::get_singleton()->free(copy_viewports_sampler);
|
||||
}
|
||||
|
||||
RasterizerRD::RasterizerRD() {
|
||||
thread_work_pool.init();
|
||||
time = 0;
|
||||
|
||||
storage = memnew(RasterizerStorageRD);
|
||||
canvas = memnew(RasterizerCanvasRD(storage));
|
||||
scene = memnew(RasterizerSceneHighEndRD(storage));
|
||||
}
|
||||
95
servers/rendering/rasterizer_rd/rasterizer_rd.h
Normal file
95
servers/rendering/rasterizer_rd/rasterizer_rd.h
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*************************************************************************/
|
||||
/* rasterizer_rd.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef RASTERIZER_RD_H
|
||||
#define RASTERIZER_RD_H
|
||||
|
||||
#include "core/os/os.h"
|
||||
#include "core/thread_work_pool.h"
|
||||
#include "servers/rendering/rasterizer.h"
|
||||
#include "servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h"
|
||||
|
||||
class RasterizerRD : public Rasterizer {
|
||||
protected:
|
||||
RasterizerCanvasRD *canvas;
|
||||
RasterizerStorageRD *storage;
|
||||
RasterizerSceneHighEndRD *scene;
|
||||
|
||||
RID copy_viewports_rd_shader;
|
||||
RID copy_viewports_rd_pipeline;
|
||||
RID copy_viewports_rd_index_buffer;
|
||||
RID copy_viewports_rd_array;
|
||||
RID copy_viewports_sampler;
|
||||
|
||||
Map<RID, RID> render_target_descriptors;
|
||||
|
||||
double time;
|
||||
|
||||
static uint32_t frame;
|
||||
|
||||
public:
|
||||
RasterizerStorage *get_storage() { return storage; }
|
||||
RasterizerCanvas *get_canvas() { return canvas; }
|
||||
RasterizerScene *get_scene() { return scene; }
|
||||
|
||||
void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {}
|
||||
|
||||
void initialize();
|
||||
void begin_frame(double frame_step);
|
||||
void prepare_for_blitting_render_targets();
|
||||
void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount);
|
||||
|
||||
void end_frame(bool p_swap_buffers);
|
||||
void finalize();
|
||||
|
||||
static _ALWAYS_INLINE_ uint64_t get_frame_number() { return frame; }
|
||||
|
||||
static Error is_viable() {
|
||||
return OK;
|
||||
}
|
||||
|
||||
static Rasterizer *_create_current() {
|
||||
return memnew(RasterizerRD);
|
||||
}
|
||||
|
||||
static void make_current() {
|
||||
_create_func = _create_current;
|
||||
}
|
||||
|
||||
virtual bool is_low_end() const { return false; }
|
||||
|
||||
static ThreadWorkPool thread_work_pool;
|
||||
|
||||
RasterizerRD();
|
||||
~RasterizerRD() {}
|
||||
};
|
||||
#endif // RASTERIZER_RD_H
|
||||
2729
servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
Normal file
2729
servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp
Normal file
File diff suppressed because it is too large
Load diff
585
servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h
Normal file
585
servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h
Normal file
|
|
@ -0,0 +1,585 @@
|
|||
/*************************************************************************/
|
||||
/* rasterizer_scene_high_end_rd.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef RASTERIZER_SCENE_HIGHEND_RD_H
|
||||
#define RASTERIZER_SCENE_HIGHEND_RD_H
|
||||
|
||||
#include "servers/rendering/rasterizer_rd/light_cluster_builder.h"
|
||||
#include "servers/rendering/rasterizer_rd/rasterizer_scene_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h"
|
||||
#include "servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl.gen.h"
|
||||
|
||||
class RasterizerSceneHighEndRD : public RasterizerSceneRD {
|
||||
|
||||
enum {
|
||||
SCENE_UNIFORM_SET = 0,
|
||||
RADIANCE_UNIFORM_SET = 1,
|
||||
VIEW_DEPENDANT_UNIFORM_SET = 2,
|
||||
RENDER_BUFFERS_UNIFORM_SET = 3,
|
||||
TRANSFORMS_UNIFORM_SET = 4,
|
||||
MATERIAL_UNIFORM_SET = 5
|
||||
};
|
||||
|
||||
/* Scene Shader */
|
||||
|
||||
enum ShaderVersion {
|
||||
SHADER_VERSION_DEPTH_PASS,
|
||||
SHADER_VERSION_DEPTH_PASS_DP,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
|
||||
SHADER_VERSION_COLOR_PASS,
|
||||
SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
|
||||
SHADER_VERSION_VCT_COLOR_PASS,
|
||||
SHADER_VERSION_VCT_COLOR_PASS_WITH_SEPARATE_SPECULAR,
|
||||
SHADER_VERSION_LIGHTMAP_COLOR_PASS,
|
||||
SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
|
||||
SHADER_VERSION_MAX
|
||||
};
|
||||
|
||||
struct {
|
||||
SceneHighEndShaderRD scene_shader;
|
||||
ShaderCompilerRD compiler;
|
||||
} shader;
|
||||
|
||||
RasterizerStorageRD *storage;
|
||||
|
||||
/* Material */
|
||||
|
||||
struct ShaderData : public RasterizerStorageRD::ShaderData {
|
||||
|
||||
enum BlendMode { //used internally
|
||||
BLEND_MODE_MIX,
|
||||
BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB,
|
||||
BLEND_MODE_MUL,
|
||||
};
|
||||
|
||||
enum DepthDraw {
|
||||
DEPTH_DRAW_DISABLED,
|
||||
DEPTH_DRAW_OPAQUE,
|
||||
DEPTH_DRAW_ALWAYS
|
||||
};
|
||||
|
||||
enum DepthTest {
|
||||
DEPTH_TEST_DISABLED,
|
||||
DEPTH_TEST_ENABLED
|
||||
};
|
||||
|
||||
enum Cull {
|
||||
CULL_DISABLED,
|
||||
CULL_FRONT,
|
||||
CULL_BACK
|
||||
};
|
||||
|
||||
enum CullVariant {
|
||||
CULL_VARIANT_NORMAL,
|
||||
CULL_VARIANT_REVERSED,
|
||||
CULL_VARIANT_DOUBLE_SIDED,
|
||||
CULL_VARIANT_MAX
|
||||
|
||||
};
|
||||
|
||||
bool valid;
|
||||
RID version;
|
||||
uint32_t vertex_input_mask;
|
||||
RenderPipelineVertexFormatCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX];
|
||||
|
||||
String path;
|
||||
|
||||
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
|
||||
Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
|
||||
|
||||
Vector<uint32_t> ubo_offsets;
|
||||
uint32_t ubo_size;
|
||||
|
||||
String code;
|
||||
Map<StringName, RID> default_texture_params;
|
||||
|
||||
DepthDraw depth_draw;
|
||||
DepthTest depth_test;
|
||||
|
||||
bool uses_point_size;
|
||||
bool uses_alpha;
|
||||
bool uses_blend_alpha;
|
||||
bool uses_depth_pre_pass;
|
||||
bool uses_discard;
|
||||
bool uses_roughness;
|
||||
bool uses_normal;
|
||||
|
||||
bool unshaded;
|
||||
bool uses_vertex;
|
||||
bool uses_sss;
|
||||
bool uses_screen_texture;
|
||||
bool uses_depth_texture;
|
||||
bool uses_normal_texture;
|
||||
bool uses_time;
|
||||
bool writes_modelview_or_projection;
|
||||
bool uses_world_coordinates;
|
||||
|
||||
uint64_t last_pass = 0;
|
||||
uint32_t index = 0;
|
||||
|
||||
virtual void set_code(const String &p_Code);
|
||||
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
|
||||
virtual void get_param_list(List<PropertyInfo> *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;
|
||||
ShaderData();
|
||||
virtual ~ShaderData();
|
||||
};
|
||||
|
||||
RasterizerStorageRD::ShaderData *_create_shader_func();
|
||||
static RasterizerStorageRD::ShaderData *_create_shader_funcs() {
|
||||
return static_cast<RasterizerSceneHighEndRD *>(singleton)->_create_shader_func();
|
||||
}
|
||||
|
||||
struct MaterialData : public RasterizerStorageRD::MaterialData {
|
||||
uint64_t last_frame;
|
||||
ShaderData *shader_data;
|
||||
RID uniform_buffer;
|
||||
RID uniform_set;
|
||||
Vector<RID> texture_cache;
|
||||
Vector<uint8_t> ubo_data;
|
||||
uint64_t last_pass = 0;
|
||||
uint32_t index = 0;
|
||||
RID next_pass;
|
||||
uint8_t priority;
|
||||
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 ~MaterialData();
|
||||
};
|
||||
|
||||
RasterizerStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
|
||||
static RasterizerStorageRD::MaterialData *_create_material_funcs(RasterizerStorageRD::ShaderData *p_shader) {
|
||||
return static_cast<RasterizerSceneHighEndRD *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
|
||||
}
|
||||
|
||||
/* Push Constant */
|
||||
|
||||
struct PushConstant {
|
||||
uint32_t index;
|
||||
uint32_t pad[3];
|
||||
};
|
||||
|
||||
/* Framebuffer */
|
||||
|
||||
struct RenderBufferDataHighEnd : public RenderBufferData {
|
||||
//for rendering, may be MSAAd
|
||||
RID color;
|
||||
RID depth;
|
||||
RID specular;
|
||||
RID normal_buffer;
|
||||
RID roughness_buffer;
|
||||
RID depth_fb;
|
||||
RID depth_normal_fb;
|
||||
RID depth_normal_roughness_fb;
|
||||
RID color_fb;
|
||||
RID color_specular_fb;
|
||||
int width, height;
|
||||
|
||||
void ensure_specular();
|
||||
void clear();
|
||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa);
|
||||
|
||||
RID uniform_set;
|
||||
|
||||
~RenderBufferDataHighEnd();
|
||||
};
|
||||
|
||||
virtual RenderBufferData *_create_render_buffer_data();
|
||||
void _allocate_normal_texture(RenderBufferDataHighEnd *rb);
|
||||
void _allocate_roughness_texture(RenderBufferDataHighEnd *rb);
|
||||
|
||||
RID shadow_sampler;
|
||||
RID render_base_uniform_set;
|
||||
RID view_dependant_uniform_set;
|
||||
|
||||
virtual void _base_uniforms_changed();
|
||||
void _render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb);
|
||||
virtual void _render_buffers_uniform_set_changed(RID p_render_buffers);
|
||||
virtual RID _render_buffers_get_roughness_texture(RID p_render_buffers);
|
||||
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers);
|
||||
|
||||
void _update_render_base_uniform_set();
|
||||
void _setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas);
|
||||
void _update_render_buffers_uniform_set(RID p_render_buffers);
|
||||
|
||||
/* Scene State UBO */
|
||||
|
||||
struct ReflectionData { //should always be 128 bytes
|
||||
float box_extents[3];
|
||||
float index;
|
||||
float box_offset[3];
|
||||
uint32_t mask;
|
||||
float params[4]; // intensity, 0, interior , boxproject
|
||||
float ambient[4]; // ambient color, energy
|
||||
float local_matrix[16]; // up to here for spot and omni, rest is for directional
|
||||
};
|
||||
|
||||
struct LightData {
|
||||
float position[3];
|
||||
float inv_radius;
|
||||
float direction[3];
|
||||
uint16_t attenuation_energy[2]; //16 bits attenuation, then energy
|
||||
uint8_t color_specular[4]; //rgb color, a specular (8 bit unorm)
|
||||
uint16_t cone_attenuation_angle[2]; // attenuation and angle, (16bit float)
|
||||
uint32_t mask;
|
||||
uint8_t shadow_color_enabled[4]; //shadow rgb color, a>0.5 enabled (8bit unorm)
|
||||
float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
|
||||
float shadow_matrix[16];
|
||||
};
|
||||
|
||||
struct DirectionalLightData {
|
||||
|
||||
float direction[3];
|
||||
float energy;
|
||||
float color[3];
|
||||
float specular;
|
||||
float shadow_color[3];
|
||||
uint32_t mask;
|
||||
uint32_t blend_splits;
|
||||
uint32_t shadow_enabled;
|
||||
float fade_from;
|
||||
float fade_to;
|
||||
float shadow_split_offsets[4];
|
||||
float shadow_matrices[4][16];
|
||||
};
|
||||
|
||||
struct GIProbeData {
|
||||
float xform[16];
|
||||
float bounds[3];
|
||||
float dynamic_range;
|
||||
|
||||
float bias;
|
||||
float normal_bias;
|
||||
uint32_t blend_ambient;
|
||||
uint32_t texture_slot;
|
||||
|
||||
float anisotropy_strength;
|
||||
float ao;
|
||||
float ao_size;
|
||||
uint32_t pad[1];
|
||||
};
|
||||
|
||||
enum {
|
||||
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14,
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15,
|
||||
INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT = 16,
|
||||
INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_MASK = 0x7,
|
||||
INSTANCE_DATA_FLAG_SKELETON = 1 << 19,
|
||||
};
|
||||
|
||||
struct InstanceData {
|
||||
float transform[16];
|
||||
float normal_transform[16];
|
||||
uint32_t flags;
|
||||
uint32_t instance_ofs; //instance_offset in instancing/skeleton buffer
|
||||
uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap)
|
||||
uint32_t mask;
|
||||
};
|
||||
|
||||
struct SceneState {
|
||||
struct UBO {
|
||||
float projection_matrix[16];
|
||||
float inv_projection_matrix[16];
|
||||
|
||||
float camera_matrix[16];
|
||||
float inv_camera_matrix[16];
|
||||
|
||||
float viewport_size[2];
|
||||
float screen_pixel_size[2];
|
||||
|
||||
float shadow_z_offset;
|
||||
float shadow_z_slope_scale;
|
||||
|
||||
float time;
|
||||
float reflection_multiplier;
|
||||
|
||||
float ambient_light_color_energy[4];
|
||||
|
||||
float ambient_color_sky_mix;
|
||||
uint32_t use_ambient_light;
|
||||
uint32_t use_ambient_cubemap;
|
||||
uint32_t use_reflection_cubemap;
|
||||
|
||||
float radiance_inverse_xform[12];
|
||||
|
||||
float shadow_atlas_pixel_size[2];
|
||||
float directional_shadow_pixel_size[2];
|
||||
|
||||
uint32_t directional_light_count;
|
||||
float dual_paraboloid_side;
|
||||
float z_far;
|
||||
float z_near;
|
||||
|
||||
uint32_t ssao_enabled;
|
||||
float ssao_light_affect;
|
||||
float ssao_ao_affect;
|
||||
uint32_t roughness_limiter_enabled;
|
||||
|
||||
float ao_color[4];
|
||||
};
|
||||
|
||||
UBO ubo;
|
||||
|
||||
RID uniform_buffer;
|
||||
|
||||
ReflectionData *reflections;
|
||||
uint32_t max_reflections;
|
||||
RID reflection_buffer;
|
||||
uint32_t max_reflection_probes_per_instance;
|
||||
|
||||
GIProbeData *gi_probes;
|
||||
uint32_t max_gi_probes;
|
||||
RID gi_probe_buffer;
|
||||
uint32_t max_gi_probe_probes_per_instance;
|
||||
|
||||
LightData *lights;
|
||||
uint32_t max_lights;
|
||||
RID light_buffer;
|
||||
|
||||
DirectionalLightData *directional_lights;
|
||||
uint32_t max_directional_lights;
|
||||
RID directional_light_buffer;
|
||||
|
||||
RID instance_buffer;
|
||||
InstanceData *instances;
|
||||
uint32_t max_instances;
|
||||
|
||||
bool used_screen_texture = false;
|
||||
bool used_normal_texture = false;
|
||||
bool used_depth_texture = false;
|
||||
bool used_sss = false;
|
||||
uint32_t current_shader_index = 0;
|
||||
uint32_t current_material_index = 0;
|
||||
} scene_state;
|
||||
|
||||
/* Render List */
|
||||
|
||||
struct RenderList {
|
||||
|
||||
int max_elements;
|
||||
|
||||
struct Element {
|
||||
RasterizerScene::InstanceBase *instance;
|
||||
MaterialData *material;
|
||||
union {
|
||||
struct {
|
||||
//from least significant to most significant in sort, TODO: should be endian swapped on big endian
|
||||
uint64_t geometry_index : 20;
|
||||
uint64_t material_index : 15;
|
||||
uint64_t shader_index : 12;
|
||||
uint64_t uses_instancing : 1;
|
||||
uint64_t uses_vct : 1;
|
||||
uint64_t uses_lightmap : 1;
|
||||
uint64_t depth_layer : 4;
|
||||
uint64_t priority : 8;
|
||||
};
|
||||
|
||||
uint64_t sort_key;
|
||||
};
|
||||
uint32_t surface_index;
|
||||
};
|
||||
|
||||
Element *base_elements;
|
||||
Element **elements;
|
||||
|
||||
int element_count;
|
||||
int alpha_element_count;
|
||||
|
||||
void clear() {
|
||||
|
||||
element_count = 0;
|
||||
alpha_element_count = 0;
|
||||
}
|
||||
|
||||
//should eventually be replaced by radix
|
||||
|
||||
struct SortByKey {
|
||||
|
||||
_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
|
||||
return A->sort_key < B->sort_key;
|
||||
}
|
||||
};
|
||||
|
||||
void sort_by_key(bool p_alpha) {
|
||||
|
||||
SortArray<Element *, SortByKey> sorter;
|
||||
if (p_alpha) {
|
||||
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
|
||||
} else {
|
||||
sorter.sort(elements, element_count);
|
||||
}
|
||||
}
|
||||
|
||||
struct SortByDepth {
|
||||
|
||||
_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
|
||||
return A->instance->depth < B->instance->depth;
|
||||
}
|
||||
};
|
||||
|
||||
void sort_by_depth(bool p_alpha) { //used for shadows
|
||||
|
||||
SortArray<Element *, SortByDepth> sorter;
|
||||
if (p_alpha) {
|
||||
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
|
||||
} else {
|
||||
sorter.sort(elements, element_count);
|
||||
}
|
||||
}
|
||||
|
||||
struct SortByReverseDepthAndPriority {
|
||||
|
||||
_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const {
|
||||
uint32_t layer_A = uint32_t(A->priority);
|
||||
uint32_t layer_B = uint32_t(B->priority);
|
||||
if (layer_A == layer_B) {
|
||||
return A->instance->depth > B->instance->depth;
|
||||
} else {
|
||||
return layer_A < layer_B;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha
|
||||
|
||||
SortArray<Element *, SortByReverseDepthAndPriority> sorter;
|
||||
if (p_alpha) {
|
||||
sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);
|
||||
} else {
|
||||
sorter.sort(elements, element_count);
|
||||
}
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Element *add_element() {
|
||||
|
||||
if (element_count + alpha_element_count >= max_elements)
|
||||
return NULL;
|
||||
elements[element_count] = &base_elements[element_count];
|
||||
return elements[element_count++];
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Element *add_alpha_element() {
|
||||
|
||||
if (element_count + alpha_element_count >= max_elements)
|
||||
return NULL;
|
||||
int idx = max_elements - alpha_element_count - 1;
|
||||
elements[idx] = &base_elements[idx];
|
||||
alpha_element_count++;
|
||||
return elements[idx];
|
||||
}
|
||||
|
||||
void init() {
|
||||
|
||||
element_count = 0;
|
||||
alpha_element_count = 0;
|
||||
elements = memnew_arr(Element *, max_elements);
|
||||
base_elements = memnew_arr(Element, max_elements);
|
||||
for (int i = 0; i < max_elements; i++)
|
||||
elements[i] = &base_elements[i]; // assign elements
|
||||
}
|
||||
|
||||
RenderList() {
|
||||
|
||||
max_elements = 0;
|
||||
}
|
||||
|
||||
~RenderList() {
|
||||
memdelete_arr(elements);
|
||||
memdelete_arr(base_elements);
|
||||
}
|
||||
};
|
||||
|
||||
RenderList render_list;
|
||||
|
||||
static RasterizerSceneHighEndRD *singleton;
|
||||
uint64_t render_pass;
|
||||
double time;
|
||||
RID default_shader;
|
||||
RID default_material;
|
||||
RID overdraw_material_shader;
|
||||
RID overdraw_material;
|
||||
RID wireframe_material_shader;
|
||||
RID wireframe_material;
|
||||
RID default_shader_rd;
|
||||
RID default_radiance_uniform_set;
|
||||
RID default_render_buffers_uniform_set;
|
||||
|
||||
RID default_vec4_xform_buffer;
|
||||
RID default_vec4_xform_uniform_set;
|
||||
|
||||
LightClusterBuilder cluster_builder;
|
||||
|
||||
enum PassMode {
|
||||
PASS_MODE_COLOR,
|
||||
PASS_MODE_COLOR_SPECULAR,
|
||||
PASS_MODE_COLOR_TRANSPARENT,
|
||||
PASS_MODE_SHADOW,
|
||||
PASS_MODE_SHADOW_DP,
|
||||
PASS_MODE_DEPTH,
|
||||
PASS_MODE_DEPTH_NORMAL,
|
||||
PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
|
||||
PASS_MODE_DEPTH_MATERIAL,
|
||||
};
|
||||
|
||||
void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false);
|
||||
void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows);
|
||||
void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment);
|
||||
void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform);
|
||||
|
||||
void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth);
|
||||
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set);
|
||||
_FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index);
|
||||
_FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index);
|
||||
|
||||
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi);
|
||||
|
||||
protected:
|
||||
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color);
|
||||
virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip);
|
||||
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region);
|
||||
|
||||
public:
|
||||
virtual void set_time(double p_time, double p_step);
|
||||
|
||||
virtual bool free(RID p_rid);
|
||||
|
||||
RasterizerSceneHighEndRD(RasterizerStorageRD *p_storage);
|
||||
~RasterizerSceneHighEndRD();
|
||||
};
|
||||
#endif // RASTERIZER_SCENE_HIGHEND_RD_H
|
||||
4039
servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
Normal file
4039
servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp
Normal file
File diff suppressed because it is too large
Load diff
1109
servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
Normal file
1109
servers/rendering/rasterizer_rd/rasterizer_scene_rd.h
Normal file
File diff suppressed because it is too large
Load diff
4822
servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
Normal file
4822
servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp
Normal file
File diff suppressed because it is too large
Load diff
1135
servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
Normal file
1135
servers/rendering/rasterizer_rd/rasterizer_storage_rd.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,97 @@
|
|||
/*************************************************************************/
|
||||
/* render_pipeline_vertex_format_cache_rd.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "render_pipeline_vertex_format_cache_rd.h"
|
||||
#include "core/os/memory.h"
|
||||
|
||||
RID RenderPipelineVertexFormatCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id) {
|
||||
|
||||
RD::PipelineMultisampleState multisample_state_version = multisample_state;
|
||||
multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id);
|
||||
|
||||
RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, rasterization_state, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags);
|
||||
ERR_FAIL_COND_V(pipeline.is_null(), RID());
|
||||
versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1));
|
||||
versions[version_count].framebuffer_id = p_framebuffer_format_id;
|
||||
versions[version_count].vertex_id = p_vertex_format_id;
|
||||
versions[version_count].pipeline = pipeline;
|
||||
version_count++;
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
void RenderPipelineVertexFormatCacheRD::_clear() {
|
||||
|
||||
if (versions) {
|
||||
for (uint32_t i = 0; i < version_count; i++) {
|
||||
//shader may be gone, so this may not be valid
|
||||
if (RD::get_singleton()->render_pipeline_is_valid(versions[i].pipeline)) {
|
||||
RD::get_singleton()->free(versions[i].pipeline);
|
||||
}
|
||||
}
|
||||
version_count = 0;
|
||||
memfree(versions);
|
||||
versions = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPipelineVertexFormatCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags) {
|
||||
ERR_FAIL_COND(p_shader.is_null());
|
||||
_clear();
|
||||
shader = p_shader;
|
||||
input_mask = RD::get_singleton()->shader_get_vertex_input_attribute_mask(p_shader);
|
||||
render_primitive = p_primitive;
|
||||
rasterization_state = p_rasterization_state;
|
||||
multisample_state = p_multisample;
|
||||
depth_stencil_state = p_depth_stencil_state;
|
||||
blend_state = p_blend_state;
|
||||
dynamic_state_flags = p_dynamic_state_flags;
|
||||
}
|
||||
|
||||
void RenderPipelineVertexFormatCacheRD::update_shader(RID p_shader) {
|
||||
ERR_FAIL_COND(p_shader.is_null());
|
||||
_clear();
|
||||
setup(p_shader, render_primitive, rasterization_state, multisample_state, depth_stencil_state, blend_state, dynamic_state_flags);
|
||||
}
|
||||
|
||||
void RenderPipelineVertexFormatCacheRD::clear() {
|
||||
_clear();
|
||||
shader = RID(); //clear shader
|
||||
input_mask = 0;
|
||||
}
|
||||
|
||||
RenderPipelineVertexFormatCacheRD::RenderPipelineVertexFormatCacheRD() {
|
||||
version_count = 0;
|
||||
versions = NULL;
|
||||
input_mask = 0;
|
||||
}
|
||||
|
||||
RenderPipelineVertexFormatCacheRD::~RenderPipelineVertexFormatCacheRD() {
|
||||
_clear();
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*************************************************************************/
|
||||
/* render_pipeline_vertex_format_cache_rd.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef RENDER_PIPELINE_CACHE_RD_H
|
||||
#define RENDER_PIPELINE_CACHE_RD_H
|
||||
|
||||
#include "core/spin_lock.h"
|
||||
#include "servers/rendering/rendering_device.h"
|
||||
|
||||
class RenderPipelineVertexFormatCacheRD {
|
||||
|
||||
SpinLock spin_lock;
|
||||
|
||||
RID shader;
|
||||
uint32_t input_mask;
|
||||
|
||||
RD::RenderPrimitive render_primitive;
|
||||
RD::PipelineRasterizationState rasterization_state;
|
||||
RD::PipelineMultisampleState multisample_state;
|
||||
RD::PipelineDepthStencilState depth_stencil_state;
|
||||
RD::PipelineColorBlendState blend_state;
|
||||
int dynamic_state_flags;
|
||||
|
||||
struct Version {
|
||||
RD::VertexFormatID vertex_id;
|
||||
RD::FramebufferFormatID framebuffer_id;
|
||||
RID pipeline;
|
||||
};
|
||||
|
||||
Version *versions;
|
||||
uint32_t version_count;
|
||||
|
||||
RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id);
|
||||
|
||||
void _clear();
|
||||
|
||||
public:
|
||||
void setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0);
|
||||
void update_shader(RID p_shader);
|
||||
|
||||
_FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ERR_FAIL_COND_V_MSG(shader.is_null(), RID(),
|
||||
"Attempted to use an unused shader variant (shader is null),");
|
||||
#endif
|
||||
|
||||
spin_lock.lock();
|
||||
RID result;
|
||||
for (uint32_t i = 0; i < version_count; i++) {
|
||||
if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id) {
|
||||
result = versions[i].pipeline;
|
||||
spin_lock.unlock();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
result = _generate_version(p_vertex_format_id, p_framebuffer_format_id);
|
||||
spin_lock.unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ uint32_t get_vertex_input_mask() const {
|
||||
return input_mask;
|
||||
}
|
||||
void clear();
|
||||
RenderPipelineVertexFormatCacheRD();
|
||||
~RenderPipelineVertexFormatCacheRD();
|
||||
};
|
||||
|
||||
#endif // RENDER_PIPELINE_CACHE_RD_H
|
||||
1243
servers/rendering/rasterizer_rd/shader_compiler_rd.cpp
Normal file
1243
servers/rendering/rasterizer_rd/shader_compiler_rd.cpp
Normal file
File diff suppressed because it is too large
Load diff
123
servers/rendering/rasterizer_rd/shader_compiler_rd.h
Normal file
123
servers/rendering/rasterizer_rd/shader_compiler_rd.h
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/*************************************************************************/
|
||||
/* shader_compiler_rd.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef SHADER_COMPILER_RD_H
|
||||
#define SHADER_COMPILER_RD_H
|
||||
|
||||
#include "core/pair.h"
|
||||
#include "servers/rendering/shader_language.h"
|
||||
#include "servers/rendering/shader_types.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
class ShaderCompilerRD {
|
||||
public:
|
||||
struct IdentifierActions {
|
||||
|
||||
Map<StringName, Pair<int *, int>> render_mode_values;
|
||||
Map<StringName, bool *> render_mode_flags;
|
||||
Map<StringName, bool *> usage_flag_pointers;
|
||||
Map<StringName, bool *> write_flag_pointers;
|
||||
|
||||
Map<StringName, ShaderLanguage::ShaderNode::Uniform> *uniforms;
|
||||
};
|
||||
|
||||
struct GeneratedCode {
|
||||
|
||||
Vector<String> defines;
|
||||
struct Texture {
|
||||
StringName name;
|
||||
ShaderLanguage::DataType type;
|
||||
ShaderLanguage::ShaderNode::Uniform::Hint hint;
|
||||
ShaderLanguage::TextureFilter filter;
|
||||
ShaderLanguage::TextureRepeat repeat;
|
||||
};
|
||||
|
||||
Vector<Texture> texture_uniforms;
|
||||
|
||||
Vector<uint32_t> uniform_offsets;
|
||||
uint32_t uniform_total_size;
|
||||
String uniforms;
|
||||
String vertex_global;
|
||||
String vertex;
|
||||
String fragment_global;
|
||||
String fragment;
|
||||
String light;
|
||||
|
||||
bool uses_fragment_time;
|
||||
bool uses_vertex_time;
|
||||
};
|
||||
|
||||
struct DefaultIdentifierActions {
|
||||
|
||||
Map<StringName, String> renames;
|
||||
Map<StringName, String> render_mode_defines;
|
||||
Map<StringName, String> usage_defines;
|
||||
Map<StringName, String> custom_samplers;
|
||||
ShaderLanguage::TextureFilter default_filter;
|
||||
ShaderLanguage::TextureRepeat default_repeat;
|
||||
String sampler_array_name;
|
||||
int base_texture_binding_index = 0;
|
||||
int texture_layout_set = 0;
|
||||
String base_uniform_string;
|
||||
uint32_t base_varying_index = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
ShaderLanguage parser;
|
||||
|
||||
String _get_sampler_name(ShaderLanguage::TextureFilter p_filter, ShaderLanguage::TextureRepeat p_repeat);
|
||||
|
||||
void _dump_function_deps(const ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map<StringName, String> &p_func_code, String &r_to_add, Set<StringName> &added);
|
||||
String _dump_node_code(const ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning);
|
||||
|
||||
const ShaderLanguage::ShaderNode *shader;
|
||||
const ShaderLanguage::FunctionNode *function;
|
||||
StringName current_func_name;
|
||||
StringName vertex_name;
|
||||
StringName fragment_name;
|
||||
StringName light_name;
|
||||
StringName time_name;
|
||||
Set<StringName> texture_functions;
|
||||
|
||||
Set<StringName> used_name_defines;
|
||||
Set<StringName> used_flag_pointers;
|
||||
Set<StringName> used_rmode_defines;
|
||||
Set<StringName> internal_functions;
|
||||
|
||||
DefaultIdentifierActions actions;
|
||||
|
||||
public:
|
||||
Error compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code);
|
||||
|
||||
void initialize(DefaultIdentifierActions p_actions);
|
||||
ShaderCompilerRD();
|
||||
};
|
||||
|
||||
#endif // SHADERCOMPILERRD_H
|
||||
495
servers/rendering/rasterizer_rd/shader_rd.cpp
Normal file
495
servers/rendering/rasterizer_rd/shader_rd.cpp
Normal file
|
|
@ -0,0 +1,495 @@
|
|||
/*************************************************************************/
|
||||
/* shader_rd.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "shader_rd.h"
|
||||
|
||||
#include "core/string_builder.h"
|
||||
#include "rasterizer_rd.h"
|
||||
#include "servers/rendering/rendering_device.h"
|
||||
|
||||
void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_compute_code, const char *p_name) {
|
||||
|
||||
name = p_name;
|
||||
//split vertex and shader code (thank you, shader compiler programmers from you know what company).
|
||||
if (p_vertex_code) {
|
||||
String defines_tag = "\nVERSION_DEFINES";
|
||||
String globals_tag = "\nVERTEX_SHADER_GLOBALS";
|
||||
String material_tag = "\nMATERIAL_UNIFORMS";
|
||||
String code_tag = "\nVERTEX_SHADER_CODE";
|
||||
String code = p_vertex_code;
|
||||
|
||||
int cpos = code.find(defines_tag);
|
||||
if (cpos != -1) {
|
||||
vertex_codev = code.substr(0, cpos).ascii();
|
||||
code = code.substr(cpos + defines_tag.length(), code.length());
|
||||
}
|
||||
|
||||
cpos = code.find(material_tag);
|
||||
|
||||
if (cpos == -1) {
|
||||
vertex_code0 = code.ascii();
|
||||
} else {
|
||||
vertex_code0 = code.substr(0, cpos).ascii();
|
||||
code = code.substr(cpos + material_tag.length(), code.length());
|
||||
|
||||
cpos = code.find(globals_tag);
|
||||
|
||||
if (cpos == -1) {
|
||||
vertex_code1 = code.ascii();
|
||||
} else {
|
||||
|
||||
vertex_code1 = code.substr(0, cpos).ascii();
|
||||
String code2 = code.substr(cpos + globals_tag.length(), code.length());
|
||||
|
||||
cpos = code2.find(code_tag);
|
||||
if (cpos == -1) {
|
||||
vertex_code2 = code2.ascii();
|
||||
} else {
|
||||
|
||||
vertex_code2 = code2.substr(0, cpos).ascii();
|
||||
vertex_code3 = code2.substr(cpos + code_tag.length(), code2.length()).ascii();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_fragment_code) {
|
||||
String defines_tag = "\nVERSION_DEFINES";
|
||||
String globals_tag = "\nFRAGMENT_SHADER_GLOBALS";
|
||||
String material_tag = "\nMATERIAL_UNIFORMS";
|
||||
String code_tag = "\nFRAGMENT_SHADER_CODE";
|
||||
String light_code_tag = "\nLIGHT_SHADER_CODE";
|
||||
String code = p_fragment_code;
|
||||
|
||||
int cpos = code.find(defines_tag);
|
||||
if (cpos != -1) {
|
||||
fragment_codev = code.substr(0, cpos).ascii();
|
||||
code = code.substr(cpos + defines_tag.length(), code.length());
|
||||
}
|
||||
|
||||
cpos = code.find(material_tag);
|
||||
if (cpos == -1) {
|
||||
fragment_code0 = code.ascii();
|
||||
} else {
|
||||
fragment_code0 = code.substr(0, cpos).ascii();
|
||||
//print_line("CODE0:\n"+String(fragment_code0.get_data()));
|
||||
code = code.substr(cpos + material_tag.length(), code.length());
|
||||
cpos = code.find(globals_tag);
|
||||
|
||||
if (cpos == -1) {
|
||||
fragment_code1 = code.ascii();
|
||||
} else {
|
||||
|
||||
fragment_code1 = code.substr(0, cpos).ascii();
|
||||
//print_line("CODE1:\n"+String(fragment_code1.get_data()));
|
||||
|
||||
String code2 = code.substr(cpos + globals_tag.length(), code.length());
|
||||
cpos = code2.find(light_code_tag);
|
||||
|
||||
if (cpos == -1) {
|
||||
fragment_code2 = code2.ascii();
|
||||
} else {
|
||||
|
||||
fragment_code2 = code2.substr(0, cpos).ascii();
|
||||
//print_line("CODE2:\n"+String(fragment_code2.get_data()));
|
||||
|
||||
String code3 = code2.substr(cpos + light_code_tag.length(), code2.length());
|
||||
|
||||
cpos = code3.find(code_tag);
|
||||
if (cpos == -1) {
|
||||
fragment_code3 = code3.ascii();
|
||||
} else {
|
||||
|
||||
fragment_code3 = code3.substr(0, cpos).ascii();
|
||||
//print_line("CODE3:\n"+String(fragment_code3.get_data()));
|
||||
fragment_code4 = code3.substr(cpos + code_tag.length(), code3.length()).ascii();
|
||||
//print_line("CODE4:\n"+String(fragment_code4.get_data()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_compute_code) {
|
||||
is_compute = true;
|
||||
|
||||
String defines_tag = "\nVERSION_DEFINES";
|
||||
String globals_tag = "\nCOMPUTE_SHADER_GLOBALS";
|
||||
String material_tag = "\nMATERIAL_UNIFORMS";
|
||||
String code_tag = "\nCOMPUTE_SHADER_CODE";
|
||||
String code = p_compute_code;
|
||||
|
||||
int cpos = code.find(defines_tag);
|
||||
if (cpos != -1) {
|
||||
compute_codev = code.substr(0, cpos).ascii();
|
||||
code = code.substr(cpos + defines_tag.length(), code.length());
|
||||
}
|
||||
|
||||
cpos = code.find(material_tag);
|
||||
|
||||
if (cpos == -1) {
|
||||
compute_code0 = code.ascii();
|
||||
} else {
|
||||
compute_code0 = code.substr(0, cpos).ascii();
|
||||
code = code.substr(cpos + material_tag.length(), code.length());
|
||||
|
||||
cpos = code.find(globals_tag);
|
||||
|
||||
if (cpos == -1) {
|
||||
compute_code1 = code.ascii();
|
||||
} else {
|
||||
|
||||
compute_code1 = code.substr(0, cpos).ascii();
|
||||
String code2 = code.substr(cpos + globals_tag.length(), code.length());
|
||||
|
||||
cpos = code2.find(code_tag);
|
||||
if (cpos == -1) {
|
||||
compute_code2 = code2.ascii();
|
||||
} else {
|
||||
|
||||
compute_code2 = code2.substr(0, cpos).ascii();
|
||||
compute_code3 = code2.substr(cpos + code_tag.length(), code2.length()).ascii();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RID ShaderRD::version_create() {
|
||||
|
||||
//initialize() was never called
|
||||
ERR_FAIL_COND_V(variant_defines.size() == 0, RID());
|
||||
|
||||
Version version;
|
||||
version.dirty = true;
|
||||
version.valid = false;
|
||||
version.initialize_needed = true;
|
||||
version.variants = NULL;
|
||||
return version_owner.make_rid(version);
|
||||
}
|
||||
|
||||
void ShaderRD::_clear_version(Version *p_version) {
|
||||
//clear versions if they exist
|
||||
if (p_version->variants) {
|
||||
for (int i = 0; i < variant_defines.size(); i++) {
|
||||
RD::get_singleton()->free(p_version->variants[i]);
|
||||
}
|
||||
|
||||
memdelete_arr(p_version->variants);
|
||||
p_version->variants = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
|
||||
|
||||
Vector<RD::ShaderStageData> stages;
|
||||
|
||||
String error;
|
||||
String current_source;
|
||||
RD::ShaderStage current_stage = RD::SHADER_STAGE_VERTEX;
|
||||
bool build_ok = true;
|
||||
|
||||
if (!is_compute) {
|
||||
//vertex stage
|
||||
|
||||
StringBuilder builder;
|
||||
|
||||
builder.append(vertex_codev.get_data()); // version info (if exists)
|
||||
builder.append("\n"); //make sure defines begin at newline
|
||||
builder.append(general_defines.get_data());
|
||||
builder.append(variant_defines[p_variant].get_data());
|
||||
|
||||
for (int j = 0; j < p_version->custom_defines.size(); j++) {
|
||||
builder.append(p_version->custom_defines[j].get_data());
|
||||
}
|
||||
|
||||
builder.append(vertex_code0.get_data()); //first part of vertex
|
||||
|
||||
builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment)
|
||||
|
||||
builder.append(vertex_code1.get_data()); //second part of vertex
|
||||
|
||||
builder.append(p_version->vertex_globals.get_data()); // vertex globals
|
||||
|
||||
builder.append(vertex_code2.get_data()); //third part of vertex
|
||||
|
||||
builder.append(p_version->vertex_code.get_data()); // code
|
||||
|
||||
builder.append(vertex_code3.get_data()); //fourth of vertex
|
||||
|
||||
current_source = builder.as_string();
|
||||
RD::ShaderStageData stage;
|
||||
stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_VERTEX, current_source, RD::SHADER_LANGUAGE_GLSL, &error);
|
||||
if (stage.spir_v.size() == 0) {
|
||||
build_ok = false;
|
||||
} else {
|
||||
|
||||
stage.shader_stage = RD::SHADER_STAGE_VERTEX;
|
||||
stages.push_back(stage);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_compute && build_ok) {
|
||||
//fragment stage
|
||||
current_stage = RD::SHADER_STAGE_FRAGMENT;
|
||||
|
||||
StringBuilder builder;
|
||||
|
||||
builder.append(fragment_codev.get_data()); // version info (if exists)
|
||||
builder.append("\n"); //make sure defines begin at newline
|
||||
|
||||
builder.append(general_defines.get_data());
|
||||
builder.append(variant_defines[p_variant].get_data());
|
||||
for (int j = 0; j < p_version->custom_defines.size(); j++) {
|
||||
builder.append(p_version->custom_defines[j].get_data());
|
||||
}
|
||||
|
||||
builder.append(fragment_code0.get_data()); //first part of fragment
|
||||
|
||||
builder.append(p_version->uniforms.get_data()); //uniforms (same for fragment and fragment)
|
||||
|
||||
builder.append(fragment_code1.get_data()); //first part of fragment
|
||||
|
||||
builder.append(p_version->fragment_globals.get_data()); // fragment globals
|
||||
|
||||
builder.append(fragment_code2.get_data()); //third part of fragment
|
||||
|
||||
builder.append(p_version->fragment_light.get_data()); // fragment light
|
||||
|
||||
builder.append(fragment_code3.get_data()); //fourth part of fragment
|
||||
|
||||
builder.append(p_version->fragment_code.get_data()); // fragment code
|
||||
|
||||
builder.append(fragment_code4.get_data()); //fourth part of fragment
|
||||
|
||||
current_source = builder.as_string();
|
||||
RD::ShaderStageData stage;
|
||||
stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_FRAGMENT, current_source, RD::SHADER_LANGUAGE_GLSL, &error);
|
||||
if (stage.spir_v.size() == 0) {
|
||||
build_ok = false;
|
||||
} else {
|
||||
|
||||
stage.shader_stage = RD::SHADER_STAGE_FRAGMENT;
|
||||
stages.push_back(stage);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_compute) {
|
||||
//compute stage
|
||||
current_stage = RD::SHADER_STAGE_COMPUTE;
|
||||
|
||||
StringBuilder builder;
|
||||
|
||||
builder.append(compute_codev.get_data()); // version info (if exists)
|
||||
builder.append("\n"); //make sure defines begin at newline
|
||||
builder.append(general_defines.get_data());
|
||||
builder.append(variant_defines[p_variant].get_data());
|
||||
|
||||
for (int j = 0; j < p_version->custom_defines.size(); j++) {
|
||||
builder.append(p_version->custom_defines[j].get_data());
|
||||
}
|
||||
|
||||
builder.append(compute_code0.get_data()); //first part of compute
|
||||
|
||||
builder.append(p_version->uniforms.get_data()); //uniforms (same for compute and fragment)
|
||||
|
||||
builder.append(compute_code1.get_data()); //second part of compute
|
||||
|
||||
builder.append(p_version->compute_globals.get_data()); // compute globals
|
||||
|
||||
builder.append(compute_code2.get_data()); //third part of compute
|
||||
|
||||
builder.append(p_version->compute_code.get_data()); // code
|
||||
|
||||
builder.append(compute_code3.get_data()); //fourth of compute
|
||||
|
||||
current_source = builder.as_string();
|
||||
RD::ShaderStageData stage;
|
||||
stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_COMPUTE, current_source, RD::SHADER_LANGUAGE_GLSL, &error);
|
||||
if (stage.spir_v.size() == 0) {
|
||||
build_ok = false;
|
||||
} else {
|
||||
|
||||
stage.shader_stage = RD::SHADER_STAGE_COMPUTE;
|
||||
stages.push_back(stage);
|
||||
}
|
||||
}
|
||||
|
||||
if (!build_ok) {
|
||||
MutexLock lock(variant_set_mutex); //properly print the errors
|
||||
ERR_PRINT("Error compiling " + String(current_stage == RD::SHADER_STAGE_COMPUTE ? "Compute " : (current_stage == RD::SHADER_STAGE_VERTEX ? "Vertex" : "Fragment")) + " shader, variant #" + itos(p_variant) + " (" + variant_defines[p_variant].get_data() + ").");
|
||||
ERR_PRINT(error);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
ERR_PRINT("code:\n" + current_source.get_with_code_lines());
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
RID shader = RD::get_singleton()->shader_create(stages);
|
||||
{
|
||||
MutexLock lock(variant_set_mutex);
|
||||
p_version->variants[p_variant] = shader;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderRD::_compile_version(Version *p_version) {
|
||||
|
||||
_clear_version(p_version);
|
||||
|
||||
p_version->valid = false;
|
||||
p_version->dirty = false;
|
||||
|
||||
p_version->variants = memnew_arr(RID, variant_defines.size());
|
||||
#if 1
|
||||
|
||||
RasterizerRD::thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version);
|
||||
#else
|
||||
for (int i = 0; i < variant_defines.size(); i++) {
|
||||
|
||||
_compile_variant(i, p_version);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool all_valid = true;
|
||||
for (int i = 0; i < variant_defines.size(); i++) {
|
||||
if (p_version->variants[i].is_null()) {
|
||||
all_valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!all_valid) {
|
||||
//clear versions if they exist
|
||||
for (int i = 0; i < variant_defines.size(); i++) {
|
||||
if (!p_version->variants[i].is_null()) {
|
||||
RD::get_singleton()->free(p_version->variants[i]);
|
||||
}
|
||||
}
|
||||
memdelete_arr(p_version->variants);
|
||||
p_version->variants = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
p_version->valid = true;
|
||||
}
|
||||
|
||||
void ShaderRD::version_set_code(RID p_version, const String &p_uniforms, const String &p_vertex_globals, const String &p_vertex_code, const String &p_fragment_globals, const String &p_fragment_light, const String &p_fragment_code, const Vector<String> &p_custom_defines) {
|
||||
|
||||
ERR_FAIL_COND(is_compute);
|
||||
|
||||
Version *version = version_owner.getornull(p_version);
|
||||
ERR_FAIL_COND(!version);
|
||||
version->vertex_globals = p_vertex_globals.utf8();
|
||||
version->vertex_code = p_vertex_code.utf8();
|
||||
version->fragment_light = p_fragment_light.utf8();
|
||||
version->fragment_globals = p_fragment_globals.utf8();
|
||||
version->fragment_code = p_fragment_code.utf8();
|
||||
version->uniforms = p_uniforms.utf8();
|
||||
|
||||
version->custom_defines.clear();
|
||||
for (int i = 0; i < p_custom_defines.size(); i++) {
|
||||
version->custom_defines.push_back(p_custom_defines[i].utf8());
|
||||
}
|
||||
|
||||
version->dirty = true;
|
||||
if (version->initialize_needed) {
|
||||
_compile_version(version);
|
||||
version->initialize_needed = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderRD::version_set_compute_code(RID p_version, const String &p_uniforms, const String &p_compute_globals, const String &p_compute_code, const Vector<String> &p_custom_defines) {
|
||||
|
||||
ERR_FAIL_COND(!is_compute);
|
||||
|
||||
Version *version = version_owner.getornull(p_version);
|
||||
ERR_FAIL_COND(!version);
|
||||
version->compute_globals = p_compute_globals.utf8();
|
||||
version->compute_code = p_compute_code.utf8();
|
||||
version->uniforms = p_uniforms.utf8();
|
||||
|
||||
version->custom_defines.clear();
|
||||
for (int i = 0; i < p_custom_defines.size(); i++) {
|
||||
version->custom_defines.push_back(p_custom_defines[i].utf8());
|
||||
}
|
||||
|
||||
version->dirty = true;
|
||||
if (version->initialize_needed) {
|
||||
_compile_version(version);
|
||||
version->initialize_needed = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ShaderRD::version_is_valid(RID p_version) {
|
||||
Version *version = version_owner.getornull(p_version);
|
||||
ERR_FAIL_COND_V(!version, false);
|
||||
|
||||
if (version->dirty) {
|
||||
_compile_version(version);
|
||||
}
|
||||
|
||||
return version->valid;
|
||||
}
|
||||
|
||||
bool ShaderRD::version_free(RID p_version) {
|
||||
|
||||
if (version_owner.owns(p_version)) {
|
||||
Version *version = version_owner.getornull(p_version);
|
||||
_clear_version(version);
|
||||
version_owner.free(p_version);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String &p_general_defines) {
|
||||
ERR_FAIL_COND(variant_defines.size());
|
||||
ERR_FAIL_COND(p_variant_defines.size() == 0);
|
||||
general_defines = p_general_defines.utf8();
|
||||
for (int i = 0; i < p_variant_defines.size(); i++) {
|
||||
|
||||
variant_defines.push_back(p_variant_defines[i].utf8());
|
||||
}
|
||||
}
|
||||
|
||||
ShaderRD::~ShaderRD() {
|
||||
List<RID> remaining;
|
||||
version_owner.get_owned_list(&remaining);
|
||||
if (remaining.size()) {
|
||||
ERR_PRINT(itos(remaining.size()) + " shaders of type " + name + " were never freed");
|
||||
while (remaining.size()) {
|
||||
version_free(remaining.front()->get());
|
||||
remaining.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
136
servers/rendering/rasterizer_rd/shader_rd.h
Normal file
136
servers/rendering/rasterizer_rd/shader_rd.h
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/*************************************************************************/
|
||||
/* shader_rd.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef SHADER_RD_H
|
||||
#define SHADER_RD_H
|
||||
|
||||
#include "core/hash_map.h"
|
||||
#include "core/map.h"
|
||||
#include "core/os/mutex.h"
|
||||
#include "core/rid_owner.h"
|
||||
#include "core/variant.h"
|
||||
|
||||
#include <stdio.h>
|
||||
/**
|
||||
@author Juan Linietsky <reduzio@gmail.com>
|
||||
*/
|
||||
|
||||
class ShaderRD {
|
||||
|
||||
//versions
|
||||
CharString general_defines;
|
||||
Vector<CharString> variant_defines;
|
||||
|
||||
struct Version {
|
||||
CharString uniforms;
|
||||
CharString vertex_globals;
|
||||
CharString vertex_code;
|
||||
CharString compute_globals;
|
||||
CharString compute_code;
|
||||
CharString fragment_light;
|
||||
CharString fragment_globals;
|
||||
CharString fragment_code;
|
||||
Vector<CharString> custom_defines;
|
||||
|
||||
RID *variants; //same size as version defines
|
||||
|
||||
bool valid;
|
||||
bool dirty;
|
||||
bool initialize_needed;
|
||||
};
|
||||
|
||||
Mutex variant_set_mutex;
|
||||
|
||||
void _compile_variant(uint32_t p_variant, Version *p_version);
|
||||
|
||||
void _clear_version(Version *p_version);
|
||||
void _compile_version(Version *p_version);
|
||||
|
||||
RID_Owner<Version> version_owner;
|
||||
|
||||
CharString fragment_codev; //for version and extensions
|
||||
CharString fragment_code0;
|
||||
CharString fragment_code1;
|
||||
CharString fragment_code2;
|
||||
CharString fragment_code3;
|
||||
CharString fragment_code4;
|
||||
|
||||
CharString vertex_codev; //for version and extensions
|
||||
CharString vertex_code0;
|
||||
CharString vertex_code1;
|
||||
CharString vertex_code2;
|
||||
CharString vertex_code3;
|
||||
|
||||
bool is_compute = false;
|
||||
|
||||
CharString compute_codev; //for version and extensions
|
||||
CharString compute_code0;
|
||||
CharString compute_code1;
|
||||
CharString compute_code2;
|
||||
CharString compute_code3;
|
||||
|
||||
const char *name;
|
||||
|
||||
protected:
|
||||
ShaderRD() {}
|
||||
void setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_compute_code, const char *p_name);
|
||||
|
||||
public:
|
||||
RID version_create();
|
||||
|
||||
void version_set_code(RID p_version, const String &p_uniforms, const String &p_vertex_globals, const String &p_vertex_code, const String &p_fragment_globals, const String &p_fragment_light, const String &p_fragment_code, const Vector<String> &p_custom_defines);
|
||||
void version_set_compute_code(RID p_version, const String &p_uniforms, const String &p_compute_globals, const String &p_compute_code, const Vector<String> &p_custom_defines);
|
||||
|
||||
_FORCE_INLINE_ RID version_get_shader(RID p_version, int p_variant) {
|
||||
ERR_FAIL_INDEX_V(p_variant, variant_defines.size(), RID());
|
||||
|
||||
Version *version = version_owner.getornull(p_version);
|
||||
ERR_FAIL_COND_V(!version, RID());
|
||||
|
||||
if (version->dirty) {
|
||||
_compile_version(version);
|
||||
}
|
||||
|
||||
if (!version->valid) {
|
||||
return RID();
|
||||
}
|
||||
|
||||
return version->variants[p_variant];
|
||||
}
|
||||
|
||||
bool version_is_valid(RID p_version);
|
||||
|
||||
bool version_free(RID p_version);
|
||||
|
||||
void initialize(const Vector<String> &p_variant_defines, const String &p_general_defines = "");
|
||||
virtual ~ShaderRD();
|
||||
};
|
||||
|
||||
#endif
|
||||
24
servers/rendering/rasterizer_rd/shaders/SCsub
Normal file
24
servers/rendering/rasterizer_rd/shaders/SCsub
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
Import('env')
|
||||
|
||||
if 'RD_GLSL' in env['BUILDERS']:
|
||||
env.RD_GLSL('canvas.glsl');
|
||||
env.RD_GLSL('canvas_occlusion.glsl');
|
||||
env.RD_GLSL('blur.glsl');
|
||||
env.RD_GLSL('cubemap_roughness.glsl');
|
||||
env.RD_GLSL('cubemap_downsampler.glsl');
|
||||
env.RD_GLSL('cubemap_filter.glsl');
|
||||
env.RD_GLSL('scene_high_end.glsl');
|
||||
env.RD_GLSL('sky.glsl');
|
||||
env.RD_GLSL('tonemap.glsl');
|
||||
env.RD_GLSL('copy.glsl');
|
||||
env.RD_GLSL('giprobe.glsl');
|
||||
env.RD_GLSL('giprobe_debug.glsl');
|
||||
env.RD_GLSL('giprobe_sdf.glsl');
|
||||
env.RD_GLSL('luminance_reduce.glsl');
|
||||
env.RD_GLSL('bokeh_dof.glsl');
|
||||
env.RD_GLSL('ssao.glsl');
|
||||
env.RD_GLSL('ssao_minify.glsl');
|
||||
env.RD_GLSL('ssao_blur.glsl');
|
||||
env.RD_GLSL('roughness_limiter.glsl');
|
||||
294
servers/rendering/rasterizer_rd/shaders/blur.glsl
Normal file
294
servers/rendering/rasterizer_rd/shaders/blur.glsl
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
/* clang-format off */
|
||||
[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
#include "blur_inc.glsl"
|
||||
|
||||
layout(location = 0) out vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
void main() {
|
||||
|
||||
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
||||
uv_interp = base_arr[gl_VertexIndex];
|
||||
|
||||
if (bool(blur.flags & FLAG_USE_BLUR_SECTION)) {
|
||||
uv_interp = blur.section.xy + uv_interp * blur.section.zw;
|
||||
}
|
||||
|
||||
gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
|
||||
|
||||
if (bool(blur.flags & FLAG_FLIP_Y)) {
|
||||
uv_interp.y = 1.0 - uv_interp.y;
|
||||
}
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
[fragment]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
#include "blur_inc.glsl"
|
||||
|
||||
layout(location = 0) in vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_color;
|
||||
|
||||
#ifdef MODE_SSAO_MERGE
|
||||
layout(set = 1, binding = 0) uniform sampler2D source_ssao;
|
||||
#endif
|
||||
|
||||
#ifdef GLOW_USE_AUTO_EXPOSURE
|
||||
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
|
||||
#endif
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
//DOF
|
||||
#if defined(MODE_DOF_FAR_BLUR) || defined(MODE_DOF_NEAR_BLUR)
|
||||
|
||||
layout(set = 1, binding = 0) uniform sampler2D dof_source_depth;
|
||||
|
||||
#ifdef DOF_NEAR_BLUR_MERGE
|
||||
layout(set = 2, binding = 0) uniform sampler2D source_dof_original;
|
||||
#endif
|
||||
|
||||
#ifdef DOF_QUALITY_LOW
|
||||
const int dof_kernel_size = 5;
|
||||
const int dof_kernel_from = 2;
|
||||
const float dof_kernel[5] = float[](0.153388, 0.221461, 0.250301, 0.221461, 0.153388);
|
||||
#endif
|
||||
|
||||
#ifdef DOF_QUALITY_MEDIUM
|
||||
const int dof_kernel_size = 11;
|
||||
const int dof_kernel_from = 5;
|
||||
const float dof_kernel[11] = float[](0.055037, 0.072806, 0.090506, 0.105726, 0.116061, 0.119726, 0.116061, 0.105726, 0.090506, 0.072806, 0.055037);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef DOF_QUALITY_HIGH
|
||||
const int dof_kernel_size = 21;
|
||||
const int dof_kernel_from = 10;
|
||||
const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.046421, 0.050582, 0.054261, 0.057307, 0.059587, 0.060998, 0.061476, 0.060998, 0.059587, 0.057307, 0.054261, 0.050582, 0.046421, 0.041944, 0.037311, 0.032676, 0.028174);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
|
||||
#ifdef MODE_MIPMAP
|
||||
|
||||
vec2 pix_size = blur.pixel_size;
|
||||
vec4 color = texture(source_color, uv_interp + vec2(-0.5, -0.5) * pix_size);
|
||||
color += texture(source_color, uv_interp + vec2(0.5, -0.5) * pix_size);
|
||||
color += texture(source_color, uv_interp + vec2(0.5, 0.5) * pix_size);
|
||||
color += texture(source_color, uv_interp + vec2(-0.5, 0.5) * pix_size);
|
||||
frag_color = color / 4.0;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_GAUSSIAN_BLUR
|
||||
|
||||
//Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect
|
||||
|
||||
if (bool(blur.flags & FLAG_HORIZONTAL)) {
|
||||
|
||||
vec2 pix_size = blur.pixel_size;
|
||||
pix_size *= 0.5; //reading from larger buffer, so use more samples
|
||||
vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.214607;
|
||||
color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.189879;
|
||||
color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.131514;
|
||||
color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.071303;
|
||||
color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.189879;
|
||||
color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.131514;
|
||||
color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.071303;
|
||||
frag_color = color;
|
||||
} else {
|
||||
|
||||
vec2 pix_size = blur.pixel_size;
|
||||
vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.38774;
|
||||
color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.24477;
|
||||
color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.06136;
|
||||
color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.24477;
|
||||
color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.06136;
|
||||
frag_color = color;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MODE_GAUSSIAN_GLOW
|
||||
|
||||
//Glow uses larger sigma 1 for a more rounded blur effect
|
||||
|
||||
#define GLOW_ADD(m_ofs, m_mult) \
|
||||
{ \
|
||||
vec2 ofs = uv_interp + m_ofs * pix_size; \
|
||||
vec4 c = texture(source_color, ofs) * m_mult; \
|
||||
if (any(lessThan(ofs, vec2(0.0))) || any(greaterThan(ofs, vec2(1.0)))) { \
|
||||
c *= 0.0; \
|
||||
} \
|
||||
color += c; \
|
||||
}
|
||||
|
||||
if (bool(blur.flags & FLAG_HORIZONTAL)) {
|
||||
|
||||
vec2 pix_size = blur.pixel_size;
|
||||
pix_size *= 0.5; //reading from larger buffer, so use more samples
|
||||
vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938;
|
||||
GLOW_ADD(vec2(1.0, 0.0), 0.165569);
|
||||
GLOW_ADD(vec2(2.0, 0.0), 0.140367);
|
||||
GLOW_ADD(vec2(3.0, 0.0), 0.106595);
|
||||
GLOW_ADD(vec2(-1.0, 0.0), 0.165569);
|
||||
GLOW_ADD(vec2(-2.0, 0.0), 0.140367);
|
||||
GLOW_ADD(vec2(-3.0, 0.0), 0.106595);
|
||||
color *= blur.glow_strength;
|
||||
frag_color = color;
|
||||
} else {
|
||||
|
||||
vec2 pix_size = blur.pixel_size;
|
||||
vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.288713;
|
||||
GLOW_ADD(vec2(0.0, 1.0), 0.233062);
|
||||
GLOW_ADD(vec2(0.0, 2.0), 0.122581);
|
||||
GLOW_ADD(vec2(0.0, -1.0), 0.233062);
|
||||
GLOW_ADD(vec2(0.0, -2.0), 0.122581);
|
||||
color *= blur.glow_strength;
|
||||
frag_color = color;
|
||||
}
|
||||
|
||||
#undef GLOW_ADD
|
||||
|
||||
if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) {
|
||||
#ifdef GLOW_USE_AUTO_EXPOSURE
|
||||
|
||||
frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey;
|
||||
#endif
|
||||
frag_color *= blur.glow_exposure;
|
||||
|
||||
float luminance = max(frag_color.r, max(frag_color.g, frag_color.b));
|
||||
float feedback = max(smoothstep(blur.glow_hdr_threshold, blur.glow_hdr_threshold + blur.glow_hdr_scale, luminance), blur.glow_bloom);
|
||||
|
||||
frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_DOF_FAR_BLUR
|
||||
|
||||
vec4 color_accum = vec4(0.0);
|
||||
|
||||
float depth = texture(dof_source_depth, uv_interp, 0.0).r;
|
||||
depth = depth * 2.0 - 1.0;
|
||||
|
||||
if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
|
||||
depth = ((depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
|
||||
} else {
|
||||
depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - depth * (blur.camera_z_far - blur.camera_z_near));
|
||||
}
|
||||
|
||||
float amount = smoothstep(blur.dof_begin, blur.dof_end, depth);
|
||||
float k_accum = 0.0;
|
||||
|
||||
for (int i = 0; i < dof_kernel_size; i++) {
|
||||
|
||||
int int_ofs = i - dof_kernel_from;
|
||||
vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * amount * blur.dof_radius;
|
||||
|
||||
float tap_k = dof_kernel[i];
|
||||
|
||||
float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
|
||||
tap_depth = tap_depth * 2.0 - 1.0;
|
||||
|
||||
if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
|
||||
|
||||
tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
|
||||
} else {
|
||||
tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near));
|
||||
}
|
||||
|
||||
float tap_amount = mix(smoothstep(blur.dof_begin, blur.dof_end, tap_depth), 1.0, int_ofs == 0);
|
||||
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
|
||||
|
||||
vec4 tap_color = texture(source_color, tap_uv, 0.0) * tap_k;
|
||||
|
||||
k_accum += tap_k * tap_amount;
|
||||
color_accum += tap_color * tap_amount;
|
||||
}
|
||||
|
||||
if (k_accum > 0.0) {
|
||||
color_accum /= k_accum;
|
||||
}
|
||||
|
||||
frag_color = color_accum; ///k_accum;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_DOF_NEAR_BLUR
|
||||
|
||||
vec4 color_accum = vec4(0.0);
|
||||
|
||||
float max_accum = 0.0;
|
||||
|
||||
for (int i = 0; i < dof_kernel_size; i++) {
|
||||
|
||||
int int_ofs = i - dof_kernel_from;
|
||||
vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * blur.dof_radius;
|
||||
float ofs_influence = max(0.0, 1.0 - float(abs(int_ofs)) / float(dof_kernel_from));
|
||||
|
||||
float tap_k = dof_kernel[i];
|
||||
|
||||
vec4 tap_color = texture(source_color, tap_uv, 0.0);
|
||||
|
||||
float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r;
|
||||
tap_depth = tap_depth * 2.0 - 1.0;
|
||||
if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) {
|
||||
|
||||
tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0;
|
||||
} else {
|
||||
tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near));
|
||||
}
|
||||
float tap_amount = 1.0 - smoothstep(blur.dof_end, blur.dof_begin, tap_depth);
|
||||
tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect
|
||||
|
||||
if (bool(blur.flags & FLAG_DOF_NEAR_FIRST_TAP)) {
|
||||
tap_color.a = 1.0 - smoothstep(blur.dof_end, blur.dof_begin, tap_depth);
|
||||
}
|
||||
|
||||
max_accum = max(max_accum, tap_amount * ofs_influence);
|
||||
|
||||
color_accum += tap_color * tap_k;
|
||||
}
|
||||
|
||||
color_accum.a = max(color_accum.a, sqrt(max_accum));
|
||||
|
||||
#ifdef DOF_NEAR_BLUR_MERGE
|
||||
{
|
||||
vec4 original = texture(source_dof_original, uv_interp, 0.0);
|
||||
color_accum = mix(original, color_accum, color_accum.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bool(blur.flags & FLAG_DOF_NEAR_FIRST_TAP)) {
|
||||
frag_color = color_accum;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MODE_SIMPLE_COPY
|
||||
vec4 color = texture(source_color, uv_interp, 0.0);
|
||||
if (bool(blur.flags & FLAG_COPY_FORCE_LUMINANCE)) {
|
||||
color.rgb = vec3(max(max(color.r, color.g), color.b));
|
||||
}
|
||||
frag_color = color;
|
||||
#endif
|
||||
|
||||
#ifdef MODE_SSAO_MERGE
|
||||
vec4 color = texture(source_color, uv_interp, 0.0);
|
||||
float ssao = texture(source_ssao, uv_interp, 0.0).r;
|
||||
frag_color = vec4(mix(color.rgb, color.rgb * mix(blur.ssao_color.rgb, vec3(1.0), ssao), color.a), 1.0);
|
||||
|
||||
#endif
|
||||
}
|
||||
35
servers/rendering/rasterizer_rd/shaders/blur_inc.glsl
Normal file
35
servers/rendering/rasterizer_rd/shaders/blur_inc.glsl
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#define FLAG_HORIZONTAL (1 << 0)
|
||||
#define FLAG_USE_BLUR_SECTION (1 << 1)
|
||||
#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 2)
|
||||
#define FLAG_DOF_NEAR_FIRST_TAP (1 << 3)
|
||||
#define FLAG_GLOW_FIRST_PASS (1 << 4)
|
||||
#define FLAG_FLIP_Y (1 << 5)
|
||||
#define FLAG_COPY_FORCE_LUMINANCE (1 << 6)
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Blur {
|
||||
vec4 section;
|
||||
vec2 pixel_size;
|
||||
uint flags;
|
||||
uint pad;
|
||||
// Glow.
|
||||
float glow_strength;
|
||||
float glow_bloom;
|
||||
float glow_hdr_threshold;
|
||||
float glow_hdr_scale;
|
||||
float glow_exposure;
|
||||
float glow_white;
|
||||
float glow_luminance_cap;
|
||||
float glow_auto_exposure_grey;
|
||||
// DOF.
|
||||
float dof_begin;
|
||||
float dof_end;
|
||||
float dof_radius;
|
||||
float dof_pad;
|
||||
|
||||
vec2 dof_dir;
|
||||
float camera_z_far;
|
||||
float camera_z_near;
|
||||
|
||||
vec4 ssao_color;
|
||||
}
|
||||
blur;
|
||||
258
servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl
Normal file
258
servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
/* clang-format off */
|
||||
[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
#define BLOCK_SIZE 8
|
||||
|
||||
layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef MODE_GEN_BLUR_SIZE
|
||||
layout(rgba16f, set = 0, binding = 0) uniform restrict image2D color_image;
|
||||
layout(set = 1, binding = 0) uniform sampler2D source_depth;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_BOKEH_BOX) || defined(MODE_BOKEH_HEXAGONAL) || defined(MODE_BOKEH_CIRCULAR)
|
||||
layout(set = 1, binding = 0) uniform sampler2D color_texture;
|
||||
layout(rgba16f, set = 0, binding = 0) uniform restrict writeonly image2D bokeh_image;
|
||||
#endif
|
||||
|
||||
#ifdef MODE_COMPOSITE_BOKEH
|
||||
layout(rgba16f, set = 0, binding = 0) uniform restrict image2D color_image;
|
||||
layout(set = 1, binding = 0) uniform sampler2D source_bokeh;
|
||||
#endif
|
||||
|
||||
// based on https://www.shadertoy.com/view/Xd3GDl
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
ivec2 size;
|
||||
float z_far;
|
||||
float z_near;
|
||||
|
||||
bool orthogonal;
|
||||
float blur_size;
|
||||
float blur_scale;
|
||||
int blur_steps;
|
||||
|
||||
bool blur_near_active;
|
||||
float blur_near_begin;
|
||||
float blur_near_end;
|
||||
bool blur_far_active;
|
||||
|
||||
float blur_far_begin;
|
||||
float blur_far_end;
|
||||
bool second_pass;
|
||||
bool half_size;
|
||||
|
||||
bool use_jitter;
|
||||
float jitter_seed;
|
||||
uint pad[2];
|
||||
}
|
||||
params;
|
||||
|
||||
//used to work around downsampling filter
|
||||
#define DEPTH_GAP 0.0
|
||||
|
||||
#ifdef MODE_GEN_BLUR_SIZE
|
||||
|
||||
float get_depth_at_pos(vec2 uv) {
|
||||
float depth = textureLod(source_depth, uv, 0.0).x;
|
||||
if (params.orthogonal) {
|
||||
depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
|
||||
} else {
|
||||
depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
||||
float get_blur_size(float depth) {
|
||||
|
||||
if (params.blur_near_active && depth < params.blur_near_begin) {
|
||||
return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative
|
||||
}
|
||||
|
||||
if (params.blur_far_active && depth > params.blur_far_begin) {
|
||||
return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const float GOLDEN_ANGLE = 2.39996323;
|
||||
|
||||
//note: uniform pdf rand [0;1[
|
||||
float hash12n(vec2 p) {
|
||||
p = fract(p * vec2(5.3987, 5.4421));
|
||||
p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));
|
||||
return fract(p.x * p.y * 95.4307);
|
||||
}
|
||||
|
||||
#if defined(MODE_BOKEH_BOX) || defined(MODE_BOKEH_HEXAGONAL)
|
||||
|
||||
vec4 weighted_filter_dir(vec2 dir, vec2 uv, vec2 pixel_size) {
|
||||
|
||||
dir *= pixel_size;
|
||||
vec4 color = texture(color_texture, uv);
|
||||
|
||||
vec4 accum = color;
|
||||
float total = 1.0;
|
||||
|
||||
float blur_scale = params.blur_size / float(params.blur_steps);
|
||||
|
||||
if (params.use_jitter) {
|
||||
uv += dir * (hash12n(uv + params.jitter_seed) - 0.5);
|
||||
}
|
||||
|
||||
for (int i = -params.blur_steps; i <= params.blur_steps; i++) {
|
||||
|
||||
if (i == 0) {
|
||||
continue;
|
||||
}
|
||||
float radius = float(i) * blur_scale;
|
||||
vec2 suv = uv + dir * radius;
|
||||
radius = abs(radius);
|
||||
|
||||
vec4 sample_color = texture(color_texture, suv);
|
||||
float limit;
|
||||
|
||||
if (sample_color.a < color.a) {
|
||||
limit = abs(sample_color.a);
|
||||
} else {
|
||||
limit = abs(color.a);
|
||||
}
|
||||
|
||||
limit -= DEPTH_GAP;
|
||||
|
||||
float m = smoothstep(radius - 0.5, radius + 0.5, limit);
|
||||
|
||||
accum += mix(color, sample_color, m);
|
||||
|
||||
total += 1.0;
|
||||
}
|
||||
|
||||
return accum / total;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
|
||||
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
if (any(greaterThan(pos, params.size))) { //too large, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 pixel_size = 1.0 / vec2(params.size);
|
||||
vec2 uv = vec2(pos) / vec2(params.size);
|
||||
|
||||
#ifdef MODE_GEN_BLUR_SIZE
|
||||
uv += pixel_size * 0.5;
|
||||
//precompute size in alpha channel
|
||||
float depth = get_depth_at_pos(uv);
|
||||
float size = get_blur_size(depth);
|
||||
|
||||
vec4 color = imageLoad(color_image, pos);
|
||||
color.a = size;
|
||||
imageStore(color_image, pos, color);
|
||||
#endif
|
||||
|
||||
#ifdef MODE_BOKEH_BOX
|
||||
|
||||
//pixel_size*=0.5; //resolution is doubled
|
||||
if (params.second_pass || !params.half_size) {
|
||||
uv += pixel_size * 0.5; //half pixel to read centers
|
||||
} else {
|
||||
uv += pixel_size * 0.25; //half pixel to read centers from full res
|
||||
}
|
||||
|
||||
vec2 dir = (params.second_pass ? vec2(0.0, 1.0) : vec2(1.0, 0.0));
|
||||
|
||||
vec4 color = weighted_filter_dir(dir, uv, pixel_size);
|
||||
|
||||
imageStore(bokeh_image, pos, color);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_BOKEH_HEXAGONAL
|
||||
|
||||
//pixel_size*=0.5; //resolution is doubled
|
||||
if (params.second_pass || !params.half_size) {
|
||||
uv += pixel_size * 0.5; //half pixel to read centers
|
||||
} else {
|
||||
uv += pixel_size * 0.25; //half pixel to read centers from full res
|
||||
}
|
||||
|
||||
vec2 dir = (params.second_pass ? normalize(vec2(1.0, 0.577350269189626)) : vec2(0.0, 1.0));
|
||||
|
||||
vec4 color = weighted_filter_dir(dir, uv, pixel_size);
|
||||
|
||||
if (params.second_pass) {
|
||||
dir = normalize(vec2(-1.0, 0.577350269189626));
|
||||
|
||||
vec4 color2 = weighted_filter_dir(dir, uv, pixel_size);
|
||||
|
||||
color.rgb = min(color.rgb, color2.rgb);
|
||||
color.a = (color.a + color2.a) * 0.5;
|
||||
}
|
||||
|
||||
imageStore(bokeh_image, pos, color);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_BOKEH_CIRCULAR
|
||||
|
||||
if (params.half_size) {
|
||||
pixel_size *= 0.5; //resolution is doubled
|
||||
}
|
||||
|
||||
uv += pixel_size * 0.5; //half pixel to read centers
|
||||
|
||||
vec4 color = texture(color_texture, uv);
|
||||
float accum = 1.0;
|
||||
float radius = params.blur_scale;
|
||||
|
||||
for (float ang = 0.0; radius < params.blur_size; ang += GOLDEN_ANGLE) {
|
||||
|
||||
vec2 suv = uv + vec2(cos(ang), sin(ang)) * pixel_size * radius;
|
||||
vec4 sample_color = texture(color_texture, suv);
|
||||
float sample_size = abs(sample_color.a);
|
||||
if (sample_color.a > color.a) {
|
||||
sample_size = clamp(sample_size, 0.0, abs(color.a) * 2.0);
|
||||
}
|
||||
|
||||
float m = smoothstep(radius - 0.5, radius + 0.5, sample_size);
|
||||
color += mix(color / accum, sample_color, m);
|
||||
accum += 1.0;
|
||||
radius += params.blur_scale / radius;
|
||||
}
|
||||
|
||||
color /= accum;
|
||||
|
||||
imageStore(bokeh_image, pos, color);
|
||||
#endif
|
||||
|
||||
#ifdef MODE_COMPOSITE_BOKEH
|
||||
|
||||
uv += pixel_size * 0.5;
|
||||
vec4 color = imageLoad(color_image, pos);
|
||||
vec4 bokeh = texture(source_bokeh, uv);
|
||||
|
||||
float mix_amount;
|
||||
if (bokeh.a < color.a) {
|
||||
mix_amount = min(1.0, max(0.0, max(abs(color.a), abs(bokeh.a)) - DEPTH_GAP));
|
||||
} else {
|
||||
mix_amount = min(1.0, max(0.0, abs(color.a) - DEPTH_GAP));
|
||||
}
|
||||
|
||||
color.rgb = mix(color.rgb, bokeh.rgb, mix_amount); //blend between hires and lowres
|
||||
|
||||
color.a = 0; //reset alpha
|
||||
imageStore(color_image, pos, color);
|
||||
#endif
|
||||
}
|
||||
584
servers/rendering/rasterizer_rd/shaders/canvas.glsl
Normal file
584
servers/rendering/rasterizer_rd/shaders/canvas.glsl
Normal file
|
|
@ -0,0 +1,584 @@
|
|||
/* clang-format off */
|
||||
[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
#ifdef USE_ATTRIBUTES
|
||||
layout(location = 0) in vec2 vertex_attrib;
|
||||
/* clang-format on */
|
||||
layout(location = 3) in vec4 color_attrib;
|
||||
layout(location = 4) in vec2 uv_attrib;
|
||||
|
||||
layout(location = 6) in uvec4 bones_attrib;
|
||||
|
||||
#endif
|
||||
|
||||
#include "canvas_uniforms_inc.glsl"
|
||||
|
||||
layout(location = 0) out vec2 uv_interp;
|
||||
layout(location = 1) out vec4 color_interp;
|
||||
layout(location = 2) out vec2 vertex_interp;
|
||||
|
||||
#ifdef USE_NINEPATCH
|
||||
|
||||
layout(location = 3) out vec2 pixel_size_interp;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_MATERIAL_UNIFORMS
|
||||
layout(set = 1, binding = 1, std140) uniform MaterialUniforms{
|
||||
/* clang-format off */
|
||||
MATERIAL_UNIFORMS
|
||||
/* clang-format on */
|
||||
} material;
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
VERTEX_SHADER_GLOBALS
|
||||
/* clang-format on */
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 instance_custom = vec4(0.0);
|
||||
#ifdef USE_PRIMITIVE
|
||||
|
||||
//weird bug,
|
||||
//this works
|
||||
vec2 vertex;
|
||||
vec2 uv;
|
||||
vec4 color;
|
||||
|
||||
if (gl_VertexIndex == 0) {
|
||||
vertex = draw_data.points[0];
|
||||
uv = draw_data.uvs[0];
|
||||
color = vec4(unpackHalf2x16(draw_data.colors[0]), unpackHalf2x16(draw_data.colors[1]));
|
||||
} else if (gl_VertexIndex == 1) {
|
||||
vertex = draw_data.points[1];
|
||||
uv = draw_data.uvs[1];
|
||||
color = vec4(unpackHalf2x16(draw_data.colors[2]), unpackHalf2x16(draw_data.colors[3]));
|
||||
} else {
|
||||
vertex = draw_data.points[2];
|
||||
uv = draw_data.uvs[2];
|
||||
color = vec4(unpackHalf2x16(draw_data.colors[4]), unpackHalf2x16(draw_data.colors[5]));
|
||||
}
|
||||
uvec4 bones = uvec4(0, 0, 0, 0);
|
||||
|
||||
#elif defined(USE_ATTRIBUTES)
|
||||
|
||||
vec2 vertex = vertex_attrib;
|
||||
vec4 color = color_attrib;
|
||||
vec2 uv = uv_attrib;
|
||||
|
||||
uvec4 bones = bones_attrib;
|
||||
#else
|
||||
|
||||
vec2 vertex_base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
||||
vec2 vertex_base = vertex_base_arr[gl_VertexIndex];
|
||||
|
||||
vec2 uv = draw_data.src_rect.xy + abs(draw_data.src_rect.zw) * ((draw_data.flags & FLAGS_TRANSPOSE_RECT) != 0 ? vertex_base.yx : vertex_base.xy);
|
||||
vec4 color = draw_data.modulation;
|
||||
vec2 vertex = draw_data.dst_rect.xy + abs(draw_data.dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(draw_data.src_rect.zw, vec2(0.0, 0.0)));
|
||||
uvec4 bones = uvec4(0, 0, 0, 0);
|
||||
|
||||
#endif
|
||||
|
||||
mat4 world_matrix = mat4(vec4(draw_data.world_x, 0.0, 0.0), vec4(draw_data.world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(draw_data.world_ofs, 0.0, 1.0));
|
||||
|
||||
#if 0
|
||||
if (draw_data.flags & FLAGS_INSTANCING_ENABLED) {
|
||||
|
||||
uint offset = draw_data.flags & FLAGS_INSTANCING_STRIDE_MASK;
|
||||
offset *= gl_InstanceIndex;
|
||||
mat4 instance_xform = mat4(
|
||||
vec4(texelFetch(instancing_buffer, offset + 0), texelFetch(instancing_buffer, offset + 1), 0.0, texelFetch(instancing_buffer, offset + 3)),
|
||||
vec4(texelFetch(instancing_buffer, offset + 4), texelFetch(instancing_buffer, offset + 5), 0.0, texelFetch(instancing_buffer, offset + 7)),
|
||||
vec4(0.0, 0.0, 1.0, 0.0),
|
||||
vec4(0.0, 0.0, 0.0, 1.0));
|
||||
offset += 8;
|
||||
if (draw_data.flags & FLAGS_INSTANCING_HAS_COLORS) {
|
||||
vec4 instance_color;
|
||||
if (draw_data.flags & FLAGS_INSTANCING_COLOR_8_BIT) {
|
||||
uint bits = floatBitsToUint(texelFetch(instancing_buffer, offset));
|
||||
instance_color = unpackUnorm4x8(bits);
|
||||
offset += 1;
|
||||
} else {
|
||||
instance_color = vec4(texelFetch(instancing_buffer, offset + 0), texelFetch(instancing_buffer, offset + 1), texelFetch(instancing_buffer, offset + 2), texelFetch(instancing_buffer, offset + 3));
|
||||
offser += 4;
|
||||
}
|
||||
|
||||
color *= instance_color;
|
||||
}
|
||||
if (draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA) {
|
||||
if (draw_data.flags & FLAGS_INSTANCING_CUSTOM_DATA_8_BIT) {
|
||||
uint bits = floatBitsToUint(texelFetch(instancing_buffer, offset));
|
||||
instance_custom = unpackUnorm4x8(bits);
|
||||
} else {
|
||||
instance_custom = vec4(texelFetch(instancing_buffer, offset + 0), texelFetch(instancing_buffer, offset + 1), texelFetch(instancing_buffer, offset + 2), texelFetch(instancing_buffer, offset + 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE)
|
||||
if (bool(draw_data.flags & FLAGS_USING_PARTICLES)) {
|
||||
//scale by texture size
|
||||
vertex /= draw_data.color_texture_pixel_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_POINT_SIZE
|
||||
float point_size = 1.0;
|
||||
#endif
|
||||
{
|
||||
/* clang-format off */
|
||||
VERTEX_SHADER_CODE
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
#ifdef USE_NINEPATCH
|
||||
pixel_size_interp = abs(draw_data.dst_rect.zw) * vertex_base;
|
||||
#endif
|
||||
|
||||
#if !defined(SKIP_TRANSFORM_USED)
|
||||
vertex = (world_matrix * vec4(vertex, 0.0, 1.0)).xy;
|
||||
#endif
|
||||
|
||||
color_interp = color;
|
||||
|
||||
if (bool(draw_data.flags & FLAGS_USE_PIXEL_SNAP)) {
|
||||
|
||||
vertex = floor(vertex + 0.5);
|
||||
// precision issue on some hardware creates artifacts within texture
|
||||
// offset uv by a small amount to avoid
|
||||
uv += 1e-5;
|
||||
}
|
||||
|
||||
#ifdef USE_ATTRIBUTES
|
||||
#if 0
|
||||
if (bool(draw_data.flags & FLAGS_USE_SKELETON) && bone_weights != vec4(0.0)) { //must be a valid bone
|
||||
//skeleton transform
|
||||
|
||||
ivec4 bone_indicesi = ivec4(bone_indices);
|
||||
|
||||
uvec2 tex_ofs = bone_indicesi.x * 2;
|
||||
|
||||
mat2x4 m;
|
||||
m = mat2x4(
|
||||
texelFetch(skeleton_buffer, tex_ofs + 0),
|
||||
texelFetch(skeleton_buffer, tex_ofs + 1)) *
|
||||
bone_weights.x;
|
||||
|
||||
tex_ofs = bone_indicesi.y * 2;
|
||||
|
||||
m += mat2x4(
|
||||
texelFetch(skeleton_buffer, tex_ofs + 0),
|
||||
texelFetch(skeleton_buffer, tex_ofs + 1)) *
|
||||
bone_weights.y;
|
||||
|
||||
tex_ofs = bone_indicesi.z * 2;
|
||||
|
||||
m += mat2x4(
|
||||
texelFetch(skeleton_buffer, tex_ofs + 0),
|
||||
texelFetch(skeleton_buffer, tex_ofs + 1)) *
|
||||
bone_weights.z;
|
||||
|
||||
tex_ofs = bone_indicesi.w * 2;
|
||||
|
||||
m += mat2x4(
|
||||
texelFetch(skeleton_buffer, tex_ofs + 0),
|
||||
texelFetch(skeleton_buffer, tex_ofs + 1)) *
|
||||
bone_weights.w;
|
||||
|
||||
mat4 bone_matrix = skeleton_data.skeleton_transform * transpose(mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))) * skeleton_data.skeleton_transform_inverse;
|
||||
|
||||
//outvec = bone_matrix * outvec;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vertex = (canvas_data.canvas_transform * vec4(vertex, 0.0, 1.0)).xy;
|
||||
|
||||
vertex_interp = vertex;
|
||||
uv_interp = uv;
|
||||
|
||||
gl_Position = canvas_data.screen_transform * vec4(vertex, 0.0, 1.0);
|
||||
|
||||
#ifdef USE_POINT_SIZE
|
||||
gl_PointSize = point_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
[fragment]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
#include "canvas_uniforms_inc.glsl"
|
||||
|
||||
layout(location = 0) in vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
layout(location = 1) in vec4 color_interp;
|
||||
layout(location = 2) in vec2 vertex_interp;
|
||||
|
||||
#ifdef USE_NINEPATCH
|
||||
|
||||
layout(location = 3) in vec2 pixel_size_interp;
|
||||
|
||||
#endif
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
#ifdef USE_MATERIAL_UNIFORMS
|
||||
layout(set = 1, binding = 1, std140) uniform MaterialUniforms{
|
||||
/* clang-format off */
|
||||
MATERIAL_UNIFORMS
|
||||
/* clang-format on */
|
||||
} material;
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
FRAGMENT_SHADER_GLOBALS
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef LIGHT_SHADER_CODE_USED
|
||||
|
||||
vec4 light_compute(
|
||||
vec3 light_vertex,
|
||||
vec3 light_position,
|
||||
vec3 normal,
|
||||
vec4 light_color,
|
||||
float light_energy,
|
||||
vec4 specular_shininess,
|
||||
inout vec4 shadow_modulate,
|
||||
vec2 screen_uv,
|
||||
vec2 uv,
|
||||
vec4 color) {
|
||||
|
||||
vec4 light = vec4(0.0);
|
||||
/* clang-format off */
|
||||
LIGHT_SHADER_CODE
|
||||
/* clang-format on */
|
||||
return light;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_NINEPATCH
|
||||
|
||||
float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, int np_repeat, inout int draw_center) {
|
||||
|
||||
float tex_size = 1.0 / tex_pixel_size;
|
||||
|
||||
if (pixel < margin_begin) {
|
||||
return pixel * tex_pixel_size;
|
||||
} else if (pixel >= draw_size - margin_end) {
|
||||
return (tex_size - (draw_size - pixel)) * tex_pixel_size;
|
||||
} else {
|
||||
if (!bool(draw_data.flags & FLAGS_NINEPACH_DRAW_CENTER)) {
|
||||
draw_center--;
|
||||
}
|
||||
|
||||
// np_repeat is passed as uniform using NinePatchRect::AxisStretchMode enum.
|
||||
if (np_repeat == 0) { // Stretch.
|
||||
// Convert to ratio.
|
||||
float ratio = (pixel - margin_begin) / (draw_size - margin_begin - margin_end);
|
||||
// Scale to source texture.
|
||||
return (margin_begin + ratio * (tex_size - margin_begin - margin_end)) * tex_pixel_size;
|
||||
} else if (np_repeat == 1) { // Tile.
|
||||
// Convert to offset.
|
||||
float ofs = mod((pixel - margin_begin), tex_size - margin_begin - margin_end);
|
||||
// Scale to source texture.
|
||||
return (margin_begin + ofs) * tex_pixel_size;
|
||||
} else if (np_repeat == 2) { // Tile Fit.
|
||||
// Calculate scale.
|
||||
float src_area = draw_size - margin_begin - margin_end;
|
||||
float dst_area = tex_size - margin_begin - margin_end;
|
||||
float scale = max(1.0, floor(src_area / max(dst_area, 0.0000001) + 0.5));
|
||||
// Convert to ratio.
|
||||
float ratio = (pixel - margin_begin) / src_area;
|
||||
ratio = mod(ratio * scale, 1.0);
|
||||
// Scale to source texture.
|
||||
return (margin_begin + ratio * dst_area) * tex_pixel_size;
|
||||
} else { // Shouldn't happen, but silences compiler warning.
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 color = color_interp;
|
||||
vec2 uv = uv_interp;
|
||||
vec2 vertex = vertex_interp;
|
||||
|
||||
#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE)
|
||||
|
||||
#ifdef USE_NINEPATCH
|
||||
|
||||
int draw_center = 2;
|
||||
uv = vec2(
|
||||
map_ninepatch_axis(pixel_size_interp.x, abs(draw_data.dst_rect.z), draw_data.color_texture_pixel_size.x, draw_data.ninepatch_margins.x, draw_data.ninepatch_margins.z, int(draw_data.flags >> FLAGS_NINEPATCH_H_MODE_SHIFT) & 0x3, draw_center),
|
||||
map_ninepatch_axis(pixel_size_interp.y, abs(draw_data.dst_rect.w), draw_data.color_texture_pixel_size.y, draw_data.ninepatch_margins.y, draw_data.ninepatch_margins.w, int(draw_data.flags >> FLAGS_NINEPATCH_V_MODE_SHIFT) & 0x3, draw_center));
|
||||
|
||||
if (draw_center == 0) {
|
||||
color.a = 0.0;
|
||||
}
|
||||
|
||||
uv = uv * draw_data.src_rect.zw + draw_data.src_rect.xy; //apply region if needed
|
||||
|
||||
#endif
|
||||
if (bool(draw_data.flags & FLAGS_CLIP_RECT_UV)) {
|
||||
|
||||
uv = clamp(uv, draw_data.src_rect.xy, draw_data.src_rect.xy + abs(draw_data.src_rect.zw));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
color *= texture(sampler2D(color_texture, texture_sampler), uv);
|
||||
|
||||
uint light_count = (draw_data.flags >> FLAGS_LIGHT_COUNT_SHIFT) & 0xF; //max 16 lights
|
||||
|
||||
vec3 normal;
|
||||
|
||||
#if defined(NORMAL_USED)
|
||||
|
||||
bool normal_used = true;
|
||||
#else
|
||||
bool normal_used = false;
|
||||
#endif
|
||||
|
||||
if (normal_used || (light_count > 0 && bool(draw_data.flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) {
|
||||
normal.xy = texture(sampler2D(normal_texture, texture_sampler), uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0);
|
||||
normal.z = sqrt(1.0 - dot(normal.xy, normal.xy));
|
||||
normal_used = true;
|
||||
} else {
|
||||
normal = vec3(0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec4 specular_shininess;
|
||||
|
||||
#if defined(SPECULAR_SHININESS_USED)
|
||||
|
||||
bool specular_shininess_used = true;
|
||||
#else
|
||||
bool specular_shininess_used = false;
|
||||
#endif
|
||||
|
||||
if (specular_shininess_used || (light_count > 0 && normal_used && bool(draw_data.flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) {
|
||||
specular_shininess = texture(sampler2D(specular_texture, texture_sampler), uv);
|
||||
specular_shininess *= unpackUnorm4x8(draw_data.specular_shininess);
|
||||
specular_shininess_used = true;
|
||||
} else {
|
||||
specular_shininess = vec4(1.0);
|
||||
}
|
||||
|
||||
#if defined(SCREEN_UV_USED)
|
||||
vec2 screen_uv = gl_FragCoord.xy * canvas_data.screen_pixel_size;
|
||||
#else
|
||||
vec2 screen_uv = vec2(0.0);
|
||||
#endif
|
||||
|
||||
vec3 light_vertex = vec3(vertex, 0.0);
|
||||
vec2 shadow_vertex = vertex;
|
||||
|
||||
{
|
||||
float normal_depth = 1.0;
|
||||
|
||||
#if defined(NORMALMAP_USED)
|
||||
vec3 normal_map = vec3(0.0, 0.0, 1.0);
|
||||
normal_used = true;
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
FRAGMENT_SHADER_CODE
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#if defined(NORMALMAP_USED)
|
||||
normal = mix(vec3(0.0, 0.0, 1.0), normal_map * vec3(2.0, -2.0, 1.0) - vec3(1.0, -1.0, 0.0), normal_depth);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (normal_used) {
|
||||
//convert by item transform
|
||||
normal.xy = mat2(normalize(draw_data.world_x), normalize(draw_data.world_y)) * normal.xy;
|
||||
//convert by canvas transform
|
||||
normal = normalize((canvas_data.canvas_normal_transform * vec4(normal, 0.0)).xyz);
|
||||
}
|
||||
|
||||
vec4 base_color = color;
|
||||
if (bool(draw_data.flags & FLAGS_USING_LIGHT_MASK)) {
|
||||
color = vec4(0.0); //invisible by default due to using light mask
|
||||
}
|
||||
|
||||
color *= canvas_data.canvas_modulation;
|
||||
#ifdef USE_LIGHTING
|
||||
for (uint i = 0; i < MAX_LIGHT_TEXTURES; i++) {
|
||||
if (i >= light_count) {
|
||||
break;
|
||||
}
|
||||
uint light_base;
|
||||
if (i < 8) {
|
||||
if (i < 4) {
|
||||
light_base = draw_data.lights[0];
|
||||
} else {
|
||||
light_base = draw_data.lights[1];
|
||||
}
|
||||
} else {
|
||||
if (i < 12) {
|
||||
light_base = draw_data.lights[2];
|
||||
} else {
|
||||
light_base = draw_data.lights[3];
|
||||
}
|
||||
}
|
||||
light_base >>= (i & 3) * 8;
|
||||
light_base &= 0xFF;
|
||||
|
||||
vec2 tex_uv = (vec4(vertex, 0.0, 1.0) * mat4(light_array.data[light_base].texture_matrix[0], light_array.data[light_base].texture_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
|
||||
vec4 light_color = texture(sampler2D(light_textures[i], texture_sampler), tex_uv);
|
||||
vec4 light_base_color = light_array.data[light_base].color;
|
||||
|
||||
#ifdef LIGHT_SHADER_CODE_USED
|
||||
|
||||
vec4 shadow_modulate = vec4(1.0);
|
||||
vec3 light_position = vec3(light_array.data[light_base].position, light_array.data[light_base].height);
|
||||
|
||||
light_color.rgb *= light_base_color.rgb;
|
||||
light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, color, uv);
|
||||
#else
|
||||
|
||||
light_color.rgb *= light_base_color.rgb * light_base_color.a;
|
||||
|
||||
if (normal_used) {
|
||||
|
||||
vec3 light_pos = vec3(light_array.data[light_base].position, light_array.data[light_base].height);
|
||||
vec3 pos = light_vertex;
|
||||
vec3 light_vec = normalize(light_pos - pos);
|
||||
float cNdotL = max(0.0, dot(normal, light_vec));
|
||||
|
||||
if (specular_shininess_used) {
|
||||
//blinn
|
||||
vec3 view = vec3(0.0, 0.0, 1.0); // not great but good enough
|
||||
vec3 half_vec = normalize(view + light_vec);
|
||||
|
||||
float cNdotV = max(dot(normal, view), 0.0);
|
||||
float cNdotH = max(dot(normal, half_vec), 0.0);
|
||||
float cVdotH = max(dot(view, half_vec), 0.0);
|
||||
float cLdotH = max(dot(light_vec, half_vec), 0.0);
|
||||
float shininess = exp2(15.0 * specular_shininess.a + 1.0) * 0.25;
|
||||
float blinn = pow(cNdotH, shininess);
|
||||
blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
|
||||
float s = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75);
|
||||
|
||||
light_color.rgb = specular_shininess.rgb * light_base_color.rgb * s + light_color.rgb * cNdotL;
|
||||
} else {
|
||||
light_color.rgb *= cNdotL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (any(lessThan(tex_uv, vec2(0.0, 0.0))) || any(greaterThanEqual(tex_uv, vec2(1.0, 1.0)))) {
|
||||
//if outside the light texture, light color is zero
|
||||
light_color.a = 0.0;
|
||||
}
|
||||
|
||||
if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) {
|
||||
|
||||
vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
|
||||
|
||||
vec2 pos_norm = normalize(shadow_pos);
|
||||
vec2 pos_abs = abs(pos_norm);
|
||||
vec2 pos_box = pos_norm / max(pos_abs.x, pos_abs.y);
|
||||
vec2 pos_rot = pos_norm * mat2(vec2(0.7071067811865476, -0.7071067811865476), vec2(0.7071067811865476, 0.7071067811865476)); //is there a faster way to 45 degrees rot?
|
||||
float tex_ofs;
|
||||
float distance;
|
||||
if (pos_rot.y > 0) {
|
||||
if (pos_rot.x > 0) {
|
||||
tex_ofs = pos_box.y * 0.125 + 0.125;
|
||||
distance = shadow_pos.x;
|
||||
} else {
|
||||
tex_ofs = pos_box.x * -0.125 + (0.25 + 0.125);
|
||||
distance = shadow_pos.y;
|
||||
}
|
||||
} else {
|
||||
if (pos_rot.x < 0) {
|
||||
tex_ofs = pos_box.y * -0.125 + (0.5 + 0.125);
|
||||
distance = -shadow_pos.x;
|
||||
} else {
|
||||
tex_ofs = pos_box.x * 0.125 + (0.75 + 0.125);
|
||||
distance = -shadow_pos.y;
|
||||
}
|
||||
}
|
||||
|
||||
//float distance = length(shadow_pos);
|
||||
float shadow;
|
||||
uint shadow_mode = light_array.data[light_base].flags & LIGHT_FLAGS_FILTER_MASK;
|
||||
|
||||
vec4 shadow_uv = vec4(tex_ofs, 0.0, distance, 1.0);
|
||||
|
||||
if (shadow_mode == LIGHT_FLAGS_SHADOW_NEAREST) {
|
||||
shadow = textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x;
|
||||
} else if (shadow_mode == LIGHT_FLAGS_SHADOW_PCF5) {
|
||||
vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0);
|
||||
shadow = 0.0;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 2.0).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 2.0).x;
|
||||
shadow /= 5.0;
|
||||
} else { //PCF13
|
||||
vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0);
|
||||
shadow = 0.0;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 6.0).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 5.0).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 4.0).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 3.0).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 2.0).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 2.0).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 3.0).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 4.0).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 5.0).x;
|
||||
shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 6.0).x;
|
||||
shadow /= 13.0;
|
||||
}
|
||||
|
||||
vec4 shadow_color = light_array.data[light_base].shadow_color;
|
||||
#ifdef LIGHT_SHADER_CODE_USED
|
||||
shadow_color *= shadow_modulate;
|
||||
#endif
|
||||
light_color = mix(light_color, shadow_color, shadow);
|
||||
}
|
||||
|
||||
uint blend_mode = light_array.data[light_base].flags & LIGHT_FLAGS_BLEND_MASK;
|
||||
|
||||
switch (blend_mode) {
|
||||
case LIGHT_FLAGS_BLEND_MODE_ADD: {
|
||||
color.rgb += light_color.rgb * light_color.a;
|
||||
} break;
|
||||
case LIGHT_FLAGS_BLEND_MODE_SUB: {
|
||||
color.rgb -= light_color.rgb * light_color.a;
|
||||
} break;
|
||||
case LIGHT_FLAGS_BLEND_MODE_MIX: {
|
||||
color.rgb = mix(color.rgb, light_color.rgb, light_color.a);
|
||||
} break;
|
||||
case LIGHT_FLAGS_BLEND_MODE_MASK: {
|
||||
light_color.a *= base_color.a;
|
||||
color.rgb = mix(color.rgb, light_color.rgb, light_color.a);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
frag_color = color;
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/* clang-format off */
|
||||
[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in highp vec3 vertex;
|
||||
/* clang-format on */
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Constants {
|
||||
|
||||
mat4 projection;
|
||||
mat2x4 modelview;
|
||||
vec2 direction;
|
||||
vec2 pad;
|
||||
}
|
||||
constants;
|
||||
|
||||
layout(location = 0) out highp float depth;
|
||||
|
||||
void main() {
|
||||
|
||||
highp vec4 vtx = vec4(vertex, 1.0) * mat4(constants.modelview[0], constants.modelview[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
|
||||
depth = dot(constants.direction, vtx.xy);
|
||||
|
||||
gl_Position = constants.projection * vtx;
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
[fragment]
|
||||
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in highp float depth;
|
||||
/* clang-format on */
|
||||
layout(location = 0) out highp float distance_buf;
|
||||
|
||||
void main() {
|
||||
|
||||
distance_buf = depth;
|
||||
}
|
||||
141
servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
Normal file
141
servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
#define M_PI 3.14159265359
|
||||
|
||||
#define FLAGS_INSTANCING_STRIDE_MASK 0xF
|
||||
#define FLAGS_INSTANCING_ENABLED (1 << 4)
|
||||
#define FLAGS_INSTANCING_HAS_COLORS (1 << 5)
|
||||
#define FLAGS_INSTANCING_COLOR_8BIT (1 << 6)
|
||||
#define FLAGS_INSTANCING_HAS_CUSTOM_DATA (1 << 7)
|
||||
#define FLAGS_INSTANCING_CUSTOM_DATA_8_BIT (1 << 8)
|
||||
|
||||
#define FLAGS_CLIP_RECT_UV (1 << 9)
|
||||
#define FLAGS_TRANSPOSE_RECT (1 << 10)
|
||||
#define FLAGS_USING_LIGHT_MASK (1 << 11)
|
||||
#define FLAGS_NINEPACH_DRAW_CENTER (1 << 12)
|
||||
#define FLAGS_USING_PARTICLES (1 << 13)
|
||||
#define FLAGS_USE_PIXEL_SNAP (1 << 14)
|
||||
|
||||
#define FLAGS_NINEPATCH_H_MODE_SHIFT 16
|
||||
#define FLAGS_NINEPATCH_V_MODE_SHIFT 18
|
||||
|
||||
#define FLAGS_LIGHT_COUNT_SHIFT 20
|
||||
|
||||
#define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 26)
|
||||
#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27)
|
||||
|
||||
// In vulkan, sets should always be ordered using the following logic:
|
||||
// Lower Sets: Sets that change format and layout less often
|
||||
// Higher sets: Sets that change format and layout very often
|
||||
// This is because changing a set for another with a different layout or format,
|
||||
// invalidates all the upper ones.
|
||||
|
||||
/* SET0: Draw Primitive */
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform DrawData {
|
||||
vec2 world_x;
|
||||
vec2 world_y;
|
||||
vec2 world_ofs;
|
||||
uint flags;
|
||||
uint specular_shininess;
|
||||
#ifdef USE_PRIMITIVE
|
||||
vec2 points[3];
|
||||
vec2 uvs[3];
|
||||
uint colors[6];
|
||||
#else
|
||||
vec4 modulation;
|
||||
vec4 ninepatch_margins;
|
||||
vec4 dst_rect; //for built-in rect and UV
|
||||
vec4 src_rect;
|
||||
vec2 pad;
|
||||
|
||||
#endif
|
||||
vec2 color_texture_pixel_size;
|
||||
uint lights[4];
|
||||
}
|
||||
draw_data;
|
||||
|
||||
// The values passed per draw primitives are cached within it
|
||||
|
||||
layout(set = 0, binding = 1) uniform texture2D color_texture;
|
||||
layout(set = 0, binding = 2) uniform texture2D normal_texture;
|
||||
layout(set = 0, binding = 3) uniform texture2D specular_texture;
|
||||
layout(set = 0, binding = 4) uniform sampler texture_sampler;
|
||||
|
||||
layout(set = 0, binding = 5) uniform textureBuffer instancing_buffer;
|
||||
|
||||
/* SET1: Is reserved for the material */
|
||||
|
||||
#ifdef USE_MATERIAL_SAMPLERS
|
||||
|
||||
layout(set = 1, binding = 0) uniform sampler material_samplers[12];
|
||||
|
||||
#endif
|
||||
|
||||
/* SET2: Canvas Item State (including lighting) */
|
||||
|
||||
layout(set = 2, binding = 0, std140) uniform CanvasData {
|
||||
mat4 canvas_transform;
|
||||
mat4 screen_transform;
|
||||
mat4 canvas_normal_transform;
|
||||
vec4 canvas_modulation;
|
||||
vec2 screen_pixel_size;
|
||||
float time;
|
||||
float time_pad;
|
||||
//uint light_count;
|
||||
}
|
||||
canvas_data;
|
||||
|
||||
layout(set = 2, binding = 1) uniform textureBuffer skeleton_buffer;
|
||||
|
||||
layout(set = 2, binding = 2, std140) uniform SkeletonData {
|
||||
mat4 skeleton_transform; //in world coordinates
|
||||
mat4 skeleton_transform_inverse;
|
||||
}
|
||||
skeleton_data;
|
||||
|
||||
#ifdef USE_LIGHTING
|
||||
|
||||
#define LIGHT_FLAGS_BLEND_MASK (3 << 16)
|
||||
#define LIGHT_FLAGS_BLEND_MODE_ADD (0 << 16)
|
||||
#define LIGHT_FLAGS_BLEND_MODE_SUB (1 << 16)
|
||||
#define LIGHT_FLAGS_BLEND_MODE_MIX (2 << 16)
|
||||
#define LIGHT_FLAGS_BLEND_MODE_MASK (3 << 16)
|
||||
#define LIGHT_FLAGS_HAS_SHADOW (1 << 20)
|
||||
#define LIGHT_FLAGS_FILTER_SHIFT 22
|
||||
#define LIGHT_FLAGS_FILTER_MASK (3 << 22)
|
||||
#define LIGHT_FLAGS_SHADOW_NEAREST (0 << 22)
|
||||
#define LIGHT_FLAGS_SHADOW_PCF5 (1 << 22)
|
||||
#define LIGHT_FLAGS_SHADOW_PCF13 (2 << 22)
|
||||
|
||||
struct Light {
|
||||
mat2x4 texture_matrix; //light to texture coordinate matrix (transposed)
|
||||
mat2x4 shadow_matrix; //light to shadow coordinate matrix (transposed)
|
||||
vec4 color;
|
||||
vec4 shadow_color;
|
||||
vec2 position;
|
||||
uint flags; //index to light texture
|
||||
float height;
|
||||
float shadow_pixel_size;
|
||||
float pad0;
|
||||
float pad1;
|
||||
float pad2;
|
||||
};
|
||||
|
||||
layout(set = 2, binding = 3, std140) uniform LightData {
|
||||
Light data[MAX_LIGHTS];
|
||||
}
|
||||
light_array;
|
||||
|
||||
layout(set = 2, binding = 4) uniform texture2D light_textures[MAX_LIGHT_TEXTURES];
|
||||
layout(set = 2, binding = 5) uniform texture2D shadow_textures[MAX_LIGHT_TEXTURES];
|
||||
|
||||
layout(set = 2, binding = 6) uniform sampler shadow_sampler;
|
||||
|
||||
#endif
|
||||
|
||||
/* SET3: Render Target Data */
|
||||
|
||||
#ifdef SCREEN_TEXTURE_USED
|
||||
|
||||
layout(set = 3, binding = 0) uniform texture2D screen_texture;
|
||||
|
||||
#endif
|
||||
86
servers/rendering/rasterizer_rd/shaders/copy.glsl
Normal file
86
servers/rendering/rasterizer_rd/shaders/copy.glsl
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/* clang-format off */
|
||||
[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(location = 0) out vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
void main() {
|
||||
|
||||
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
||||
uv_interp = base_arr[gl_VertexIndex];
|
||||
|
||||
gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
[fragment]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(location = 0) in vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef MODE_CUBE_TO_DP
|
||||
|
||||
layout(set = 0, binding = 0) uniform samplerCube source_cube;
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
float bias;
|
||||
float z_far;
|
||||
float z_near;
|
||||
bool z_flip;
|
||||
}
|
||||
params;
|
||||
|
||||
layout(location = 0) out float depth_buffer;
|
||||
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
|
||||
#ifdef MODE_CUBE_TO_DP
|
||||
|
||||
vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0);
|
||||
|
||||
normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y));
|
||||
normal = normalize(normal);
|
||||
|
||||
normal.y = -normal.y; //needs to be flipped to match projection matrix
|
||||
if (!params.z_flip) {
|
||||
normal.z = -normal.z;
|
||||
}
|
||||
|
||||
float depth = texture(source_cube, normal).r;
|
||||
|
||||
// absolute values for direction cosines, bigger value equals closer to basis axis
|
||||
vec3 unorm = abs(normal);
|
||||
|
||||
if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
|
||||
// x code
|
||||
unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
|
||||
} else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
|
||||
// y code
|
||||
unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
|
||||
} else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
|
||||
// z code
|
||||
unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
|
||||
} else {
|
||||
// oh-no we messed up code
|
||||
// has to be
|
||||
unorm = vec3(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
float depth_fix = 1.0 / dot(normal, unorm);
|
||||
|
||||
depth = 2.0 * depth - 1.0;
|
||||
float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
|
||||
depth_buffer = (linear_depth * depth_fix + params.bias) / params.z_far;
|
||||
|
||||
#endif
|
||||
}
|
||||
188
servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl
Normal file
188
servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
// Copyright 2016 Activision Publishing, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
/* clang-format off */
|
||||
[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
#define BLOCK_SIZE 8
|
||||
|
||||
layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
|
||||
/* clang-format on */
|
||||
|
||||
layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
|
||||
|
||||
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap;
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
uint face_size;
|
||||
}
|
||||
params;
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
void get_dir_0(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = 1.0;
|
||||
dir[1] = v;
|
||||
dir[2] = -u;
|
||||
}
|
||||
void get_dir_1(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = -1.0;
|
||||
dir[1] = v;
|
||||
dir[2] = u;
|
||||
}
|
||||
void get_dir_2(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = u;
|
||||
dir[1] = 1.0;
|
||||
dir[2] = -v;
|
||||
}
|
||||
void get_dir_3(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = u;
|
||||
dir[1] = -1.0;
|
||||
dir[2] = v;
|
||||
}
|
||||
void get_dir_4(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = u;
|
||||
dir[1] = v;
|
||||
dir[2] = 1.0;
|
||||
}
|
||||
void get_dir_5(out vec3 dir, in float u, in float v) {
|
||||
dir[0] = -u;
|
||||
dir[1] = v;
|
||||
dir[2] = -1.0;
|
||||
}
|
||||
|
||||
float calcWeight(float u, float v) {
|
||||
float val = u * u + v * v + 1.0;
|
||||
return val * sqrt(val);
|
||||
}
|
||||
|
||||
void main() {
|
||||
uvec3 id = gl_GlobalInvocationID;
|
||||
uint face_size = params.face_size;
|
||||
|
||||
if (id.x < face_size && id.y < face_size) {
|
||||
float inv_face_size = 1.0 / float(face_size);
|
||||
|
||||
float u0 = (float(id.x) * 2.0 + 1.0 - 0.75) * inv_face_size - 1.0;
|
||||
float u1 = (float(id.x) * 2.0 + 1.0 + 0.75) * inv_face_size - 1.0;
|
||||
|
||||
float v0 = (float(id.y) * 2.0 + 1.0 - 0.75) * -inv_face_size + 1.0;
|
||||
float v1 = (float(id.y) * 2.0 + 1.0 + 0.75) * -inv_face_size + 1.0;
|
||||
|
||||
float weights[4];
|
||||
weights[0] = calcWeight(u0, v0);
|
||||
weights[1] = calcWeight(u1, v0);
|
||||
weights[2] = calcWeight(u0, v1);
|
||||
weights[3] = calcWeight(u1, v1);
|
||||
|
||||
const float wsum = 0.5 / (weights[0] + weights[1] + weights[2] + weights[3]);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
weights[i] = weights[i] * wsum + .125;
|
||||
}
|
||||
|
||||
vec3 dir;
|
||||
vec4 color;
|
||||
switch (id.z) {
|
||||
case 0:
|
||||
get_dir_0(dir, u0, v0);
|
||||
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
|
||||
|
||||
get_dir_0(dir, u1, v0);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
|
||||
|
||||
get_dir_0(dir, u0, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
|
||||
|
||||
get_dir_0(dir, u1, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
|
||||
break;
|
||||
case 1:
|
||||
get_dir_1(dir, u0, v0);
|
||||
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
|
||||
|
||||
get_dir_1(dir, u1, v0);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
|
||||
|
||||
get_dir_1(dir, u0, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
|
||||
|
||||
get_dir_1(dir, u1, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
|
||||
break;
|
||||
case 2:
|
||||
get_dir_2(dir, u0, v0);
|
||||
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
|
||||
|
||||
get_dir_2(dir, u1, v0);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
|
||||
|
||||
get_dir_2(dir, u0, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
|
||||
|
||||
get_dir_2(dir, u1, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
|
||||
break;
|
||||
case 3:
|
||||
get_dir_3(dir, u0, v0);
|
||||
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
|
||||
|
||||
get_dir_3(dir, u1, v0);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
|
||||
|
||||
get_dir_3(dir, u0, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
|
||||
|
||||
get_dir_3(dir, u1, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
|
||||
break;
|
||||
case 4:
|
||||
get_dir_4(dir, u0, v0);
|
||||
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
|
||||
|
||||
get_dir_4(dir, u1, v0);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
|
||||
|
||||
get_dir_4(dir, u0, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
|
||||
|
||||
get_dir_4(dir, u1, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
|
||||
break;
|
||||
default:
|
||||
get_dir_5(dir, u0, v0);
|
||||
color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0];
|
||||
|
||||
get_dir_5(dir, u1, v0);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1];
|
||||
|
||||
get_dir_5(dir, u0, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2];
|
||||
|
||||
get_dir_5(dir, u1, v1);
|
||||
color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3];
|
||||
break;
|
||||
}
|
||||
imageStore(dest_cubemap, ivec3(id), color);
|
||||
}
|
||||
}
|
||||
328
servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl
Normal file
328
servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
// Copyright 2016 Activision Publishing, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the Software
|
||||
// is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
/* clang-format off */
|
||||
[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
#define GROUP_SIZE 64
|
||||
|
||||
layout(local_size_x = GROUP_SIZE, local_size_y = 1, local_size_z = 1) in;
|
||||
/* clang-format on */
|
||||
|
||||
layout(set = 0, binding = 0) uniform samplerCube source_cubemap;
|
||||
layout(rgba16f, set = 2, binding = 0) uniform restrict writeonly imageCube dest_cubemap0;
|
||||
layout(rgba16f, set = 2, binding = 1) uniform restrict writeonly imageCube dest_cubemap1;
|
||||
layout(rgba16f, set = 2, binding = 2) uniform restrict writeonly imageCube dest_cubemap2;
|
||||
layout(rgba16f, set = 2, binding = 3) uniform restrict writeonly imageCube dest_cubemap3;
|
||||
layout(rgba16f, set = 2, binding = 4) uniform restrict writeonly imageCube dest_cubemap4;
|
||||
layout(rgba16f, set = 2, binding = 5) uniform restrict writeonly imageCube dest_cubemap5;
|
||||
layout(rgba16f, set = 2, binding = 6) uniform restrict writeonly imageCube dest_cubemap6;
|
||||
|
||||
#ifdef USE_HIGH_QUALITY
|
||||
#define NUM_TAPS 32
|
||||
#else
|
||||
#define NUM_TAPS 8
|
||||
#endif
|
||||
|
||||
#define BASE_RESOLUTION 128
|
||||
|
||||
#ifdef USE_HIGH_QUALITY
|
||||
layout(set = 1, binding = 0, std430) buffer restrict readonly Data {
|
||||
vec4[7][5][3][24] coeffs;
|
||||
}
|
||||
data;
|
||||
#else
|
||||
layout(set = 1, binding = 0, std430) buffer restrict readonly Data {
|
||||
vec4[7][5][6] coeffs;
|
||||
}
|
||||
data;
|
||||
#endif
|
||||
|
||||
void get_dir(out vec3 dir, in vec2 uv, in uint face) {
|
||||
switch (face) {
|
||||
case 0:
|
||||
dir = vec3(1.0, uv[1], -uv[0]);
|
||||
break;
|
||||
case 1:
|
||||
dir = vec3(-1.0, uv[1], uv[0]);
|
||||
break;
|
||||
case 2:
|
||||
dir = vec3(uv[0], 1.0, -uv[1]);
|
||||
break;
|
||||
case 3:
|
||||
dir = vec3(uv[0], -1.0, uv[1]);
|
||||
break;
|
||||
case 4:
|
||||
dir = vec3(uv[0], uv[1], 1.0);
|
||||
break;
|
||||
default:
|
||||
dir = vec3(-uv[0], uv[1], -1.0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
// INPUT:
|
||||
// id.x = the linear address of the texel (ignoring face)
|
||||
// id.y = the face
|
||||
// -> use to index output texture
|
||||
// id.x = texel x
|
||||
// id.y = texel y
|
||||
// id.z = face
|
||||
uvec3 id = gl_GlobalInvocationID;
|
||||
|
||||
// determine which texel this is
|
||||
#ifndef USE_TEXTURE_ARRAY
|
||||
// NOTE (macOS/MoltenVK): Do not rename, "level" variable name conflicts with the Metal "level(float lod)" mipmap sampling function name.
|
||||
int mip_level = 0;
|
||||
if (id.x < (128 * 128)) {
|
||||
mip_level = 0;
|
||||
} else if (id.x < (128 * 128 + 64 * 64)) {
|
||||
mip_level = 1;
|
||||
id.x -= (128 * 128);
|
||||
} else if (id.x < (128 * 128 + 64 * 64 + 32 * 32)) {
|
||||
mip_level = 2;
|
||||
id.x -= (128 * 128 + 64 * 64);
|
||||
} else if (id.x < (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16)) {
|
||||
mip_level = 3;
|
||||
id.x -= (128 * 128 + 64 * 64 + 32 * 32);
|
||||
} else if (id.x < (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8)) {
|
||||
mip_level = 4;
|
||||
id.x -= (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16);
|
||||
} else if (id.x < (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4)) {
|
||||
mip_level = 5;
|
||||
id.x -= (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8);
|
||||
} else if (id.x < (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2)) {
|
||||
mip_level = 6;
|
||||
id.x -= (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
int res = BASE_RESOLUTION >> mip_level;
|
||||
#else // Using Texture Arrays so all levels are the same resolution
|
||||
int res = BASE_RESOLUTION;
|
||||
int mip_level = int(id.x / (BASE_RESOLUTION * BASE_RESOLUTION));
|
||||
id.x -= mip_level * BASE_RESOLUTION * BASE_RESOLUTION;
|
||||
#endif
|
||||
|
||||
// determine dir / pos for the texel
|
||||
vec3 dir, adir, frameZ;
|
||||
{
|
||||
id.z = id.y;
|
||||
id.y = id.x / res;
|
||||
id.x -= id.y * res;
|
||||
|
||||
vec2 uv;
|
||||
uv.x = (float(id.x) * 2.0 + 1.0) / float(res) - 1.0;
|
||||
uv.y = -(float(id.y) * 2.0 + 1.0) / float(res) + 1.0;
|
||||
|
||||
get_dir(dir, uv, id.z);
|
||||
frameZ = normalize(dir);
|
||||
|
||||
adir = abs(dir);
|
||||
}
|
||||
|
||||
// GGX gather colors
|
||||
vec4 color = vec4(0.0);
|
||||
for (int axis = 0; axis < 3; axis++) {
|
||||
const int otherAxis0 = 1 - (axis & 1) - (axis >> 1);
|
||||
const int otherAxis1 = 2 - (axis >> 1);
|
||||
|
||||
float frameweight = (max(adir[otherAxis0], adir[otherAxis1]) - .75) / .25;
|
||||
if (frameweight > 0.0) {
|
||||
// determine frame
|
||||
vec3 UpVector;
|
||||
switch (axis) {
|
||||
case 0:
|
||||
UpVector = vec3(1, 0, 0);
|
||||
break;
|
||||
case 1:
|
||||
UpVector = vec3(0, 1, 0);
|
||||
break;
|
||||
default:
|
||||
UpVector = vec3(0, 0, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
vec3 frameX = normalize(cross(UpVector, frameZ));
|
||||
vec3 frameY = cross(frameZ, frameX);
|
||||
|
||||
// calculate parametrization for polynomial
|
||||
float Nx = dir[otherAxis0];
|
||||
float Ny = dir[otherAxis1];
|
||||
float Nz = adir[axis];
|
||||
|
||||
float NmaxXY = max(abs(Ny), abs(Nx));
|
||||
Nx /= NmaxXY;
|
||||
Ny /= NmaxXY;
|
||||
|
||||
float theta;
|
||||
if (Ny < Nx) {
|
||||
if (Ny <= -0.999)
|
||||
theta = Nx;
|
||||
else
|
||||
theta = Ny;
|
||||
} else {
|
||||
if (Ny >= 0.999)
|
||||
theta = -Nx;
|
||||
else
|
||||
theta = -Ny;
|
||||
}
|
||||
|
||||
float phi;
|
||||
if (Nz <= -0.999)
|
||||
phi = -NmaxXY;
|
||||
else if (Nz >= 0.999)
|
||||
phi = NmaxXY;
|
||||
else
|
||||
phi = Nz;
|
||||
|
||||
float theta2 = theta * theta;
|
||||
float phi2 = phi * phi;
|
||||
|
||||
// sample
|
||||
for (int iSuperTap = 0; iSuperTap < NUM_TAPS / 4; iSuperTap++) {
|
||||
const int index = (NUM_TAPS / 4) * axis + iSuperTap;
|
||||
|
||||
#ifdef USE_HIGH_QUALITY
|
||||
vec4 coeffsDir0[3];
|
||||
vec4 coeffsDir1[3];
|
||||
vec4 coeffsDir2[3];
|
||||
vec4 coeffsLevel[3];
|
||||
vec4 coeffsWeight[3];
|
||||
|
||||
for (int iCoeff = 0; iCoeff < 3; iCoeff++) {
|
||||
coeffsDir0[iCoeff] = data.coeffs[mip_level][0][iCoeff][index];
|
||||
coeffsDir1[iCoeff] = data.coeffs[mip_level][1][iCoeff][index];
|
||||
coeffsDir2[iCoeff] = data.coeffs[mip_level][2][iCoeff][index];
|
||||
coeffsLevel[iCoeff] = data.coeffs[mip_level][3][iCoeff][index];
|
||||
coeffsWeight[iCoeff] = data.coeffs[mip_level][4][iCoeff][index];
|
||||
}
|
||||
|
||||
for (int iSubTap = 0; iSubTap < 4; iSubTap++) {
|
||||
// determine sample attributes (dir, weight, mip_level)
|
||||
vec3 sample_dir = frameX * (coeffsDir0[0][iSubTap] + coeffsDir0[1][iSubTap] * theta2 + coeffsDir0[2][iSubTap] * phi2) + frameY * (coeffsDir1[0][iSubTap] + coeffsDir1[1][iSubTap] * theta2 + coeffsDir1[2][iSubTap] * phi2) + frameZ * (coeffsDir2[0][iSubTap] + coeffsDir2[1][iSubTap] * theta2 + coeffsDir2[2][iSubTap] * phi2);
|
||||
|
||||
float sample_level = coeffsLevel[0][iSubTap] + coeffsLevel[1][iSubTap] * theta2 + coeffsLevel[2][iSubTap] * phi2;
|
||||
|
||||
float sample_weight = coeffsWeight[0][iSubTap] + coeffsWeight[1][iSubTap] * theta2 + coeffsWeight[2][iSubTap] * phi2;
|
||||
#else
|
||||
vec4 coeffsDir0 = data.coeffs[mip_level][0][index];
|
||||
vec4 coeffsDir1 = data.coeffs[mip_level][1][index];
|
||||
vec4 coeffsDir2 = data.coeffs[mip_level][2][index];
|
||||
vec4 coeffsLevel = data.coeffs[mip_level][3][index];
|
||||
vec4 coeffsWeight = data.coeffs[mip_level][4][index];
|
||||
|
||||
for (int iSubTap = 0; iSubTap < 4; iSubTap++) {
|
||||
// determine sample attributes (dir, weight, mip_level)
|
||||
vec3 sample_dir = frameX * coeffsDir0[iSubTap] + frameY * coeffsDir1[iSubTap] + frameZ * coeffsDir2[iSubTap];
|
||||
|
||||
float sample_level = coeffsLevel[iSubTap];
|
||||
|
||||
float sample_weight = coeffsWeight[iSubTap];
|
||||
#endif
|
||||
|
||||
sample_weight *= frameweight;
|
||||
|
||||
// adjust for jacobian
|
||||
sample_dir /= max(abs(sample_dir[0]), max(abs(sample_dir[1]), abs(sample_dir[2])));
|
||||
sample_level += 0.75 * log2(dot(sample_dir, sample_dir));
|
||||
#ifndef USE_TEXTURE_ARRAY
|
||||
sample_level += float(mip_level) / 6.0; // Hack to increase the perceived roughness and reduce upscaling artifacts
|
||||
#endif
|
||||
// sample cubemap
|
||||
color.xyz += textureLod(source_cubemap, normalize(sample_dir), sample_level).xyz * sample_weight;
|
||||
color.w += sample_weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
color /= color.w;
|
||||
|
||||
// write color
|
||||
color.xyz = max(vec3(0.0), color.xyz);
|
||||
color.w = 1.0;
|
||||
#ifdef USE_TEXTURE_ARRAY
|
||||
id.xy *= uvec2(2, 2);
|
||||
#endif
|
||||
|
||||
switch (mip_level) {
|
||||
case 0:
|
||||
imageStore(dest_cubemap0, ivec3(id), color);
|
||||
#ifdef USE_TEXTURE_ARRAY
|
||||
imageStore(dest_cubemap0, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
|
||||
imageStore(dest_cubemap0, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
|
||||
imageStore(dest_cubemap0, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
|
||||
#endif
|
||||
break;
|
||||
case 1:
|
||||
imageStore(dest_cubemap1, ivec3(id), color);
|
||||
#ifdef USE_TEXTURE_ARRAY
|
||||
imageStore(dest_cubemap1, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
|
||||
imageStore(dest_cubemap1, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
|
||||
imageStore(dest_cubemap1, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
imageStore(dest_cubemap2, ivec3(id), color);
|
||||
#ifdef USE_TEXTURE_ARRAY
|
||||
imageStore(dest_cubemap2, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
|
||||
imageStore(dest_cubemap2, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
|
||||
imageStore(dest_cubemap2, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
|
||||
#endif
|
||||
break;
|
||||
case 3:
|
||||
imageStore(dest_cubemap3, ivec3(id), color);
|
||||
#ifdef USE_TEXTURE_ARRAY
|
||||
imageStore(dest_cubemap3, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
|
||||
imageStore(dest_cubemap3, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
|
||||
imageStore(dest_cubemap3, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
|
||||
#endif
|
||||
break;
|
||||
case 4:
|
||||
imageStore(dest_cubemap4, ivec3(id), color);
|
||||
#ifdef USE_TEXTURE_ARRAY
|
||||
imageStore(dest_cubemap4, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
|
||||
imageStore(dest_cubemap4, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
|
||||
imageStore(dest_cubemap4, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
|
||||
#endif
|
||||
break;
|
||||
case 5:
|
||||
imageStore(dest_cubemap5, ivec3(id), color);
|
||||
#ifdef USE_TEXTURE_ARRAY
|
||||
imageStore(dest_cubemap5, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
|
||||
imageStore(dest_cubemap5, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
|
||||
imageStore(dest_cubemap5, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
imageStore(dest_cubemap6, ivec3(id), color);
|
||||
#ifdef USE_TEXTURE_ARRAY
|
||||
imageStore(dest_cubemap6, ivec3(id) + ivec3(1.0, 0.0, 0.0), color);
|
||||
imageStore(dest_cubemap6, ivec3(id) + ivec3(0.0, 1.0, 0.0), color);
|
||||
imageStore(dest_cubemap6, ivec3(id) + ivec3(1.0, 1.0, 0.0), color);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
147
servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl
Normal file
147
servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/* clang-format off */
|
||||
[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
#define GROUP_SIZE 8
|
||||
|
||||
layout(local_size_x = GROUP_SIZE, local_size_y = GROUP_SIZE, local_size_z = 1) in;
|
||||
/* clang-format on */
|
||||
|
||||
layout(set = 0, binding = 0) uniform samplerCube source_cube;
|
||||
|
||||
layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap;
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
uint face_id;
|
||||
uint sample_count;
|
||||
float roughness;
|
||||
bool use_direct_write;
|
||||
float face_size;
|
||||
}
|
||||
params;
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
vec3 texelCoordToVec(vec2 uv, uint faceID) {
|
||||
mat3 faceUvVectors[6];
|
||||
|
||||
// -x
|
||||
faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z
|
||||
faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
||||
faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face
|
||||
|
||||
// +x
|
||||
faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z
|
||||
faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
||||
faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face
|
||||
|
||||
// -y
|
||||
faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
||||
faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z
|
||||
faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face
|
||||
|
||||
// +y
|
||||
faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
||||
faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z
|
||||
faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face
|
||||
|
||||
// -z
|
||||
faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x
|
||||
faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
||||
faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face
|
||||
|
||||
// +z
|
||||
faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x
|
||||
faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y
|
||||
faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face
|
||||
|
||||
// out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2].
|
||||
vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2];
|
||||
return normalize(result);
|
||||
}
|
||||
|
||||
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) {
|
||||
float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph]
|
||||
|
||||
// Compute distribution direction
|
||||
float Phi = 2.0 * M_PI * Xi.x;
|
||||
float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));
|
||||
float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
|
||||
|
||||
// Convert to spherical direction
|
||||
vec3 H;
|
||||
H.x = SinTheta * cos(Phi);
|
||||
H.y = SinTheta * sin(Phi);
|
||||
H.z = CosTheta;
|
||||
|
||||
vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 TangentX = normalize(cross(UpVector, N));
|
||||
vec3 TangentY = cross(N, TangentX);
|
||||
|
||||
// Tangent to world space
|
||||
return TangentX * H.x + TangentY * H.y + N * H.z;
|
||||
}
|
||||
|
||||
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
|
||||
float GGX(float NdotV, float a) {
|
||||
float k = a / 2.0;
|
||||
return NdotV / (NdotV * (1.0 - k) + k);
|
||||
}
|
||||
|
||||
// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html
|
||||
float G_Smith(float a, float nDotV, float nDotL) {
|
||||
return GGX(nDotL, a * a) * GGX(nDotV, a * a);
|
||||
}
|
||||
|
||||
float radicalInverse_VdC(uint bits) {
|
||||
bits = (bits << 16u) | (bits >> 16u);
|
||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||
}
|
||||
|
||||
vec2 Hammersley(uint i, uint N) {
|
||||
return vec2(float(i) / float(N), radicalInverse_VdC(i));
|
||||
}
|
||||
|
||||
void main() {
|
||||
uvec3 id = gl_GlobalInvocationID;
|
||||
id.z += params.face_id;
|
||||
|
||||
vec2 uv = ((vec2(id.xy) * 2.0 + 1.0) / (params.face_size) - 1.0);
|
||||
vec3 N = texelCoordToVec(uv, id.z);
|
||||
|
||||
//vec4 color = color_interp;
|
||||
|
||||
if (params.use_direct_write) {
|
||||
|
||||
imageStore(dest_cubemap, ivec3(id), vec4(texture(source_cube, N).rgb, 1.0));
|
||||
} else {
|
||||
|
||||
vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
for (uint sampleNum = 0u; sampleNum < params.sample_count; sampleNum++) {
|
||||
vec2 xi = Hammersley(sampleNum, params.sample_count);
|
||||
|
||||
vec3 H = ImportanceSampleGGX(xi, params.roughness, N);
|
||||
vec3 V = N;
|
||||
vec3 L = (2.0 * dot(V, H) * H - V);
|
||||
|
||||
float ndotl = clamp(dot(N, L), 0.0, 1.0);
|
||||
|
||||
if (ndotl > 0.0) {
|
||||
|
||||
sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl;
|
||||
sum.a += ndotl;
|
||||
}
|
||||
}
|
||||
sum /= sum.a;
|
||||
|
||||
imageStore(dest_cubemap, ivec3(id), vec4(sum.rgb, 1.0));
|
||||
}
|
||||
}
|
||||
788
servers/rendering/rasterizer_rd/shaders/giprobe.glsl
Normal file
788
servers/rendering/rasterizer_rd/shaders/giprobe.glsl
Normal file
|
|
@ -0,0 +1,788 @@
|
|||
/* clang-format off */
|
||||
[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
#ifdef MODE_DYNAMIC
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
#else
|
||||
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
|
||||
#endif
|
||||
/* clang-format on */
|
||||
|
||||
#ifndef MODE_DYNAMIC
|
||||
|
||||
#define NO_CHILDREN 0xFFFFFFFF
|
||||
#define GREY_VEC vec3(0.33333, 0.33333, 0.33333)
|
||||
|
||||
struct CellChildren {
|
||||
uint children[8];
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer {
|
||||
CellChildren data[];
|
||||
}
|
||||
cell_children;
|
||||
|
||||
struct CellData {
|
||||
uint position; // xyz 10 bits
|
||||
uint albedo; //rgb albedo
|
||||
uint emission; //rgb normalized with e as multiplier
|
||||
uint normal; //RGB normal encoded
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 2, std430) buffer CellDataBuffer {
|
||||
CellData data[];
|
||||
}
|
||||
cell_data;
|
||||
|
||||
#endif // MODE DYNAMIC
|
||||
|
||||
#define LIGHT_TYPE_DIRECTIONAL 0
|
||||
#define LIGHT_TYPE_OMNI 1
|
||||
#define LIGHT_TYPE_SPOT 2
|
||||
|
||||
#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING)
|
||||
|
||||
struct Light {
|
||||
|
||||
uint type;
|
||||
float energy;
|
||||
float radius;
|
||||
float attenuation;
|
||||
|
||||
vec3 color;
|
||||
float spot_angle_radians;
|
||||
|
||||
vec3 position;
|
||||
float spot_attenuation;
|
||||
|
||||
vec3 direction;
|
||||
bool has_shadow;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 3, std140) uniform Lights {
|
||||
Light data[MAX_LIGHTS];
|
||||
}
|
||||
lights;
|
||||
|
||||
#endif // MODE COMPUTE LIGHT
|
||||
|
||||
#ifdef MODE_SECOND_BOUNCE
|
||||
|
||||
layout(set = 0, binding = 5) uniform texture3D color_texture;
|
||||
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
layout(set = 0, binding = 7) uniform texture3D aniso_pos_texture;
|
||||
layout(set = 0, binding = 8) uniform texture3D aniso_neg_texture;
|
||||
#endif // MODE ANISOTROPIC
|
||||
|
||||
#endif // MODE_SECOND_BOUNCE
|
||||
|
||||
#ifndef MODE_DYNAMIC
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
ivec3 limits;
|
||||
uint stack_size;
|
||||
|
||||
float emission_scale;
|
||||
float propagation;
|
||||
float dynamic_range;
|
||||
|
||||
uint light_count;
|
||||
uint cell_offset;
|
||||
uint cell_count;
|
||||
float aniso_strength;
|
||||
uint pad;
|
||||
}
|
||||
params;
|
||||
|
||||
layout(set = 0, binding = 4, std430) buffer Outputs {
|
||||
vec4 data[];
|
||||
}
|
||||
outputs;
|
||||
|
||||
#endif // MODE DYNAMIC
|
||||
|
||||
layout(set = 0, binding = 9) uniform texture3D texture_sdf;
|
||||
layout(set = 0, binding = 10) uniform sampler texture_sampler;
|
||||
|
||||
#ifdef MODE_WRITE_TEXTURE
|
||||
|
||||
layout(rgba8, set = 0, binding = 5) uniform restrict writeonly image3D color_tex;
|
||||
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
|
||||
layout(r16ui, set = 0, binding = 6) uniform restrict writeonly uimage3D aniso_pos_tex;
|
||||
layout(r16ui, set = 0, binding = 7) uniform restrict writeonly uimage3D aniso_neg_tex;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_DYNAMIC
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
ivec3 limits;
|
||||
uint light_count; //when not lighting
|
||||
ivec3 x_dir;
|
||||
float z_base;
|
||||
ivec3 y_dir;
|
||||
float z_sign;
|
||||
ivec3 z_dir;
|
||||
float pos_multiplier;
|
||||
ivec2 rect_pos;
|
||||
ivec2 rect_size;
|
||||
ivec2 prev_rect_ofs;
|
||||
ivec2 prev_rect_size;
|
||||
bool flip_x;
|
||||
bool flip_y;
|
||||
float dynamic_range;
|
||||
bool on_mipmap;
|
||||
float propagation;
|
||||
float pad[3];
|
||||
}
|
||||
params;
|
||||
|
||||
#ifdef MODE_DYNAMIC_LIGHTING
|
||||
|
||||
layout(rgba8, set = 0, binding = 5) uniform restrict readonly image2D source_albedo;
|
||||
layout(rgba8, set = 0, binding = 6) uniform restrict readonly image2D source_normal;
|
||||
layout(rgba8, set = 0, binding = 7) uniform restrict readonly image2D source_orm;
|
||||
//layout (set=0,binding=8) uniform texture2D source_depth;
|
||||
layout(rgba16f, set = 0, binding = 11) uniform restrict image2D emission;
|
||||
layout(r32f, set = 0, binding = 12) uniform restrict image2D depth;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_DYNAMIC_SHRINK
|
||||
|
||||
layout(rgba16f, set = 0, binding = 5) uniform restrict readonly image2D source_light;
|
||||
layout(r32f, set = 0, binding = 6) uniform restrict readonly image2D source_depth;
|
||||
|
||||
#ifdef MODE_DYNAMIC_SHRINK_WRITE
|
||||
|
||||
layout(rgba16f, set = 0, binding = 7) uniform restrict writeonly image2D light;
|
||||
layout(r32f, set = 0, binding = 8) uniform restrict writeonly image2D depth;
|
||||
|
||||
#endif // MODE_DYNAMIC_SHRINK_WRITE
|
||||
|
||||
#ifdef MODE_DYNAMIC_SHRINK_PLOT
|
||||
|
||||
layout(rgba8, set = 0, binding = 11) uniform restrict image3D color_texture;
|
||||
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
|
||||
layout(r16ui, set = 0, binding = 12) uniform restrict writeonly uimage3D aniso_pos_texture;
|
||||
layout(r16ui, set = 0, binding = 13) uniform restrict writeonly uimage3D aniso_neg_texture;
|
||||
|
||||
#endif // MODE ANISOTROPIC
|
||||
|
||||
#endif //MODE_DYNAMIC_SHRINK_PLOT
|
||||
|
||||
#endif // MODE_DYNAMIC_SHRINK
|
||||
|
||||
//layout (rgba8,set=0,binding=5) uniform restrict writeonly image3D color_tex;
|
||||
|
||||
#endif // MODE DYNAMIC
|
||||
|
||||
#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING)
|
||||
|
||||
float raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
|
||||
|
||||
vec3 cell_size = 1.0 / vec3(params.limits);
|
||||
float occlusion = 1.0;
|
||||
while (distance > 0.5) { //use this to avoid precision errors
|
||||
float advance = texture(sampler3D(texture_sdf, texture_sampler), from * cell_size).r * 255.0 - 1.0;
|
||||
if (advance < 0.0) {
|
||||
occlusion = 0.0;
|
||||
break;
|
||||
}
|
||||
|
||||
occlusion = min(advance, occlusion);
|
||||
|
||||
advance = max(distance_adv, advance - mod(advance, distance_adv)); //should always advance in multiples of distance_adv
|
||||
|
||||
from += direction * advance;
|
||||
distance -= advance;
|
||||
}
|
||||
|
||||
return occlusion; //max(0.0,distance);
|
||||
}
|
||||
|
||||
bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3 light_pos) {
|
||||
|
||||
if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) {
|
||||
|
||||
light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
|
||||
attenuation = 1.0;
|
||||
|
||||
} else {
|
||||
|
||||
light_pos = lights.data[light].position;
|
||||
float distance = length(pos - light_pos);
|
||||
if (distance >= lights.data[light].radius) {
|
||||
return false;
|
||||
}
|
||||
|
||||
attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation);
|
||||
|
||||
if (lights.data[light].type == LIGHT_TYPE_SPOT) {
|
||||
|
||||
vec3 rel = normalize(pos - light_pos);
|
||||
float angle = acos(dot(rel, lights.data[light].direction));
|
||||
if (angle > lights.data[light].spot_angle_radians) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1);
|
||||
attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float get_normal_advance(vec3 p_normal) {
|
||||
|
||||
vec3 normal = p_normal;
|
||||
vec3 unorm = abs(normal);
|
||||
|
||||
if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
|
||||
// x code
|
||||
unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
|
||||
} else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
|
||||
// y code
|
||||
unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
|
||||
} else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
|
||||
// z code
|
||||
unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
|
||||
} else {
|
||||
// oh-no we messed up code
|
||||
// has to be
|
||||
unorm = vec3(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
return 1.0 / dot(normal, unorm);
|
||||
}
|
||||
|
||||
void clip_segment(vec4 plane, vec3 begin, inout vec3 end) {
|
||||
|
||||
vec3 segment = begin - end;
|
||||
float den = dot(plane.xyz, segment);
|
||||
|
||||
//printf("den is %i\n",den);
|
||||
if (den < 0.0001) {
|
||||
return;
|
||||
}
|
||||
|
||||
float dist = (dot(plane.xyz, begin) - plane.w) / den;
|
||||
|
||||
if (dist < 0.0001 || dist > 1.0001) {
|
||||
return;
|
||||
}
|
||||
|
||||
end = begin + segment * -dist;
|
||||
}
|
||||
|
||||
bool compute_light_at_pos(uint index, vec3 pos, vec3 normal, inout vec3 light, inout vec3 light_dir) {
|
||||
float attenuation;
|
||||
vec3 light_pos;
|
||||
|
||||
if (!compute_light_vector(index, pos, attenuation, light_pos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
light_dir = normalize(pos - light_pos);
|
||||
|
||||
if (attenuation < 0.01 || (length(normal) > 0.2 && dot(normal, light_dir) >= 0)) {
|
||||
return false; //not facing the light, or attenuation is near zero
|
||||
}
|
||||
|
||||
if (lights.data[index].has_shadow) {
|
||||
|
||||
float distance_adv = get_normal_advance(light_dir);
|
||||
|
||||
vec3 to = pos;
|
||||
if (length(normal) > 0.2) {
|
||||
to += normal * distance_adv * 0.51;
|
||||
} else {
|
||||
to -= sign(light_dir) * 0.45; //go near the edge towards the light direction to avoid self occlusion
|
||||
}
|
||||
|
||||
//clip
|
||||
clip_segment(mix(vec4(-1.0, 0.0, 0.0, 0.0), vec4(1.0, 0.0, 0.0, float(params.limits.x - 1)), bvec4(light_dir.x < 0.0)), to, light_pos);
|
||||
clip_segment(mix(vec4(0.0, -1.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, float(params.limits.y - 1)), bvec4(light_dir.y < 0.0)), to, light_pos);
|
||||
clip_segment(mix(vec4(0.0, 0.0, -1.0, 0.0), vec4(0.0, 0.0, 1.0, float(params.limits.z - 1)), bvec4(light_dir.z < 0.0)), to, light_pos);
|
||||
|
||||
float distance = length(to - light_pos);
|
||||
if (distance < 0.1) {
|
||||
return false; // hit
|
||||
}
|
||||
|
||||
distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always
|
||||
light_pos = to - light_dir * distance;
|
||||
|
||||
//from -= sign(light_dir)*0.45; //go near the edge towards the light direction to avoid self occlusion
|
||||
|
||||
/*float dist = raymarch(distance,distance_adv,light_pos,light_dir);
|
||||
|
||||
if (dist > distance_adv) {
|
||||
return false;
|
||||
}
|
||||
|
||||
attenuation *= 1.0 - smoothstep(0.1*distance_adv,distance_adv,dist);
|
||||
*/
|
||||
|
||||
float occlusion = raymarch(distance, distance_adv, light_pos, light_dir);
|
||||
|
||||
if (occlusion == 0.0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
attenuation *= occlusion; //1.0 - smoothstep(0.1*distance_adv,distance_adv,dist);
|
||||
}
|
||||
|
||||
light = lights.data[index].color * attenuation * lights.data[index].energy;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // MODE COMPUTE LIGHT
|
||||
|
||||
void main() {
|
||||
|
||||
#ifndef MODE_DYNAMIC
|
||||
|
||||
uint cell_index = gl_GlobalInvocationID.x;
|
||||
if (cell_index >= params.cell_count) {
|
||||
return;
|
||||
}
|
||||
cell_index += params.cell_offset;
|
||||
|
||||
uvec3 posu = uvec3(cell_data.data[cell_index].position & 0x7FF, (cell_data.data[cell_index].position >> 11) & 0x3FF, cell_data.data[cell_index].position >> 21);
|
||||
vec4 albedo = unpackUnorm4x8(cell_data.data[cell_index].albedo);
|
||||
|
||||
#endif
|
||||
|
||||
/////////////////COMPUTE LIGHT///////////////////////////////
|
||||
|
||||
#ifdef MODE_COMPUTE_LIGHT
|
||||
|
||||
vec3 pos = vec3(posu) + vec3(0.5);
|
||||
|
||||
vec3 emission = vec3(uvec3(cell_data.data[cell_index].emission & 0x1ff, (cell_data.data[cell_index].emission >> 9) & 0x1ff, (cell_data.data[cell_index].emission >> 18) & 0x1ff)) * pow(2.0, float(cell_data.data[cell_index].emission >> 27) - 15.0 - 9.0);
|
||||
vec3 normal = unpackSnorm4x8(cell_data.data[cell_index].normal).xyz;
|
||||
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
vec3 accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
|
||||
const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0));
|
||||
#else
|
||||
vec3 accum = vec3(0.0);
|
||||
#endif
|
||||
|
||||
for (uint i = 0; i < params.light_count; i++) {
|
||||
|
||||
vec3 light;
|
||||
vec3 light_dir;
|
||||
if (!compute_light_at_pos(i, pos, normal.xyz, light, light_dir)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
light *= albedo.rgb;
|
||||
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
for (uint j = 0; j < 6; j++) {
|
||||
|
||||
accum[j] += max(0.0, dot(accum_dirs[j], -light_dir)) * light;
|
||||
}
|
||||
#else
|
||||
if (length(normal) > 0.2) {
|
||||
accum += max(0.0, dot(normal, -light_dir)) * light;
|
||||
} else {
|
||||
//all directions
|
||||
accum += light;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
|
||||
for (uint i = 0; i < 6; i++) {
|
||||
vec3 light = accum[i];
|
||||
if (length(normal) > 0.2) {
|
||||
light += max(0.0, dot(accum_dirs[i], -normal)) * emission;
|
||||
} else {
|
||||
light += emission;
|
||||
}
|
||||
|
||||
outputs.data[cell_index * 6 + i] = vec4(light, 0.0);
|
||||
}
|
||||
|
||||
#else
|
||||
outputs.data[cell_index] = vec4(accum + emission, 0.0);
|
||||
|
||||
#endif
|
||||
|
||||
#endif //MODE_COMPUTE_LIGHT
|
||||
|
||||
/////////////////SECOND BOUNCE///////////////////////////////
|
||||
|
||||
#ifdef MODE_SECOND_BOUNCE
|
||||
vec3 pos = vec3(posu) + vec3(0.5);
|
||||
ivec3 ipos = ivec3(posu);
|
||||
vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal);
|
||||
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
vec3 accum[6];
|
||||
const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0));
|
||||
|
||||
/*vec3 src_color = texelFetch(sampler3D(color_texture,texture_sampler),ipos,0).rgb * params.dynamic_range;
|
||||
vec3 src_aniso_pos = texelFetch(sampler3D(aniso_pos_texture,texture_sampler),ipos,0).rgb;
|
||||
vec3 src_anisp_neg = texelFetch(sampler3D(anisp_neg_texture,texture_sampler),ipos,0).rgb;
|
||||
accum[0]=src_col * src_aniso_pos.x;
|
||||
accum[1]=src_col * src_aniso_neg.x;
|
||||
accum[2]=src_col * src_aniso_pos.y;
|
||||
accum[3]=src_col * src_aniso_neg.y;
|
||||
accum[4]=src_col * src_aniso_pos.z;
|
||||
accum[5]=src_col * src_aniso_neg.z;*/
|
||||
|
||||
accum[0] = outputs.data[cell_index * 6 + 0].rgb;
|
||||
accum[1] = outputs.data[cell_index * 6 + 1].rgb;
|
||||
accum[2] = outputs.data[cell_index * 6 + 2].rgb;
|
||||
accum[3] = outputs.data[cell_index * 6 + 3].rgb;
|
||||
accum[4] = outputs.data[cell_index * 6 + 4].rgb;
|
||||
accum[5] = outputs.data[cell_index * 6 + 5].rgb;
|
||||
|
||||
#else
|
||||
vec3 accum = outputs.data[cell_index].rgb;
|
||||
|
||||
#endif
|
||||
|
||||
if (length(normal.xyz) > 0.2) {
|
||||
|
||||
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
|
||||
vec3 tangent = normalize(cross(v0, normal.xyz));
|
||||
vec3 bitangent = normalize(cross(tangent, normal.xyz));
|
||||
mat3 normal_mat = mat3(tangent, bitangent, normal.xyz);
|
||||
|
||||
#define MAX_CONE_DIRS 6
|
||||
|
||||
vec3 cone_dirs[MAX_CONE_DIRS] = vec3[](
|
||||
vec3(0.0, 0.0, 1.0),
|
||||
vec3(0.866025, 0.0, 0.5),
|
||||
vec3(0.267617, 0.823639, 0.5),
|
||||
vec3(-0.700629, 0.509037, 0.5),
|
||||
vec3(-0.700629, -0.509037, 0.5),
|
||||
vec3(0.267617, -0.823639, 0.5));
|
||||
|
||||
float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15);
|
||||
float tan_half_angle = 0.577;
|
||||
|
||||
for (int i = 0; i < MAX_CONE_DIRS; i++) {
|
||||
|
||||
vec3 direction = normal_mat * cone_dirs[i];
|
||||
vec4 color = vec4(0.0);
|
||||
{
|
||||
|
||||
float dist = 1.5;
|
||||
float max_distance = length(vec3(params.limits));
|
||||
vec3 cell_size = 1.0 / vec3(params.limits);
|
||||
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
vec3 aniso_normal = mix(direction, normal.xyz, params.aniso_strength);
|
||||
#endif
|
||||
while (dist < max_distance && color.a < 0.95) {
|
||||
float diameter = max(1.0, 2.0 * tan_half_angle * dist);
|
||||
vec3 uvw_pos = (pos + dist * direction) * cell_size;
|
||||
float half_diameter = diameter * 0.5;
|
||||
//check if outside, then break
|
||||
//if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + half_diameter * cell_size)) ) ) {
|
||||
// break;
|
||||
//}
|
||||
|
||||
float log2_diameter = log2(diameter);
|
||||
vec4 scolor = textureLod(sampler3D(color_texture, texture_sampler), uvw_pos, log2_diameter);
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
|
||||
vec3 aniso_neg = textureLod(sampler3D(aniso_neg_texture, texture_sampler), uvw_pos, log2_diameter).rgb;
|
||||
vec3 aniso_pos = textureLod(sampler3D(aniso_pos_texture, texture_sampler), uvw_pos, log2_diameter).rgb;
|
||||
|
||||
scolor.rgb *= dot(max(vec3(0.0), (aniso_normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-aniso_normal * aniso_neg)), vec3(1.0));
|
||||
#endif
|
||||
float a = (1.0 - color.a);
|
||||
color += a * scolor;
|
||||
dist += half_diameter;
|
||||
}
|
||||
}
|
||||
color *= cone_weights[i] * vec4(albedo.rgb, 1.0) * params.dynamic_range; //restore range
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
for (uint j = 0; j < 6; j++) {
|
||||
|
||||
accum[j] += max(0.0, dot(accum_dirs[j], direction)) * color.rgb;
|
||||
}
|
||||
#else
|
||||
accum += color.rgb;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
|
||||
outputs.data[cell_index * 6 + 0] = vec4(accum[0], 0.0);
|
||||
outputs.data[cell_index * 6 + 1] = vec4(accum[1], 0.0);
|
||||
outputs.data[cell_index * 6 + 2] = vec4(accum[2], 0.0);
|
||||
outputs.data[cell_index * 6 + 3] = vec4(accum[3], 0.0);
|
||||
outputs.data[cell_index * 6 + 4] = vec4(accum[4], 0.0);
|
||||
outputs.data[cell_index * 6 + 5] = vec4(accum[5], 0.0);
|
||||
#else
|
||||
outputs.data[cell_index] = vec4(accum, 0.0);
|
||||
|
||||
#endif
|
||||
|
||||
#endif // MODE_SECOND_BOUNCE
|
||||
|
||||
/////////////////UPDATE MIPMAPS///////////////////////////////
|
||||
|
||||
#ifdef MODE_UPDATE_MIPMAPS
|
||||
|
||||
{
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
vec3 light_accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
|
||||
#else
|
||||
vec3 light_accum = vec3(0.0);
|
||||
#endif
|
||||
float count = 0.0;
|
||||
for (uint i = 0; i < 8; i++) {
|
||||
uint child_index = cell_children.data[cell_index].children[i];
|
||||
if (child_index == NO_CHILDREN) {
|
||||
continue;
|
||||
}
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
light_accum[0] += outputs.data[child_index * 6 + 0].rgb;
|
||||
light_accum[1] += outputs.data[child_index * 6 + 1].rgb;
|
||||
light_accum[2] += outputs.data[child_index * 6 + 2].rgb;
|
||||
light_accum[3] += outputs.data[child_index * 6 + 3].rgb;
|
||||
light_accum[4] += outputs.data[child_index * 6 + 4].rgb;
|
||||
light_accum[5] += outputs.data[child_index * 6 + 5].rgb;
|
||||
|
||||
#else
|
||||
light_accum += outputs.data[child_index].rgb;
|
||||
|
||||
#endif
|
||||
|
||||
count += 1.0;
|
||||
}
|
||||
|
||||
float divisor = mix(8.0, count, params.propagation);
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
outputs.data[cell_index * 6 + 0] = vec4(light_accum[0] / divisor, 0.0);
|
||||
outputs.data[cell_index * 6 + 1] = vec4(light_accum[1] / divisor, 0.0);
|
||||
outputs.data[cell_index * 6 + 2] = vec4(light_accum[2] / divisor, 0.0);
|
||||
outputs.data[cell_index * 6 + 3] = vec4(light_accum[3] / divisor, 0.0);
|
||||
outputs.data[cell_index * 6 + 4] = vec4(light_accum[4] / divisor, 0.0);
|
||||
outputs.data[cell_index * 6 + 5] = vec4(light_accum[5] / divisor, 0.0);
|
||||
|
||||
#else
|
||||
outputs.data[cell_index] = vec4(light_accum / divisor, 0.0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
///////////////////WRITE TEXTURE/////////////////////////////
|
||||
|
||||
#ifdef MODE_WRITE_TEXTURE
|
||||
{
|
||||
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
vec3 accum_total = vec3(0.0);
|
||||
accum_total += outputs.data[cell_index * 6 + 0].rgb;
|
||||
accum_total += outputs.data[cell_index * 6 + 1].rgb;
|
||||
accum_total += outputs.data[cell_index * 6 + 2].rgb;
|
||||
accum_total += outputs.data[cell_index * 6 + 3].rgb;
|
||||
accum_total += outputs.data[cell_index * 6 + 4].rgb;
|
||||
accum_total += outputs.data[cell_index * 6 + 5].rgb;
|
||||
|
||||
float accum_total_energy = max(dot(accum_total, GREY_VEC), 0.00001);
|
||||
vec3 iso_positive = vec3(dot(outputs.data[cell_index * 6 + 0].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 2].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 4].rgb, GREY_VEC)) / vec3(accum_total_energy);
|
||||
vec3 iso_negative = vec3(dot(outputs.data[cell_index * 6 + 1].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 3].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 5].rgb, GREY_VEC)) / vec3(accum_total_energy);
|
||||
|
||||
{
|
||||
uint aniso_pos = uint(clamp(iso_positive.b * 31.0, 0.0, 31.0));
|
||||
aniso_pos |= uint(clamp(iso_positive.g * 63.0, 0.0, 63.0)) << 5;
|
||||
aniso_pos |= uint(clamp(iso_positive.r * 31.0, 0.0, 31.0)) << 11;
|
||||
imageStore(aniso_pos_tex, ivec3(posu), uvec4(aniso_pos));
|
||||
}
|
||||
|
||||
{
|
||||
uint aniso_neg = uint(clamp(iso_negative.b * 31.0, 0.0, 31.0));
|
||||
aniso_neg |= uint(clamp(iso_negative.g * 63.0, 0.0, 63.0)) << 5;
|
||||
aniso_neg |= uint(clamp(iso_negative.r * 31.0, 0.0, 31.0)) << 11;
|
||||
imageStore(aniso_neg_tex, ivec3(posu), uvec4(aniso_neg));
|
||||
}
|
||||
|
||||
imageStore(color_tex, ivec3(posu), vec4(accum_total / params.dynamic_range, albedo.a));
|
||||
|
||||
#else
|
||||
|
||||
imageStore(color_tex, ivec3(posu), vec4(outputs.data[cell_index].rgb / params.dynamic_range, albedo.a));
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
///////////////////DYNAMIC LIGHTING/////////////////////////////
|
||||
|
||||
#ifdef MODE_DYNAMIC
|
||||
|
||||
ivec2 pos_xy = ivec2(gl_GlobalInvocationID.xy);
|
||||
if (any(greaterThanEqual(pos_xy, params.rect_size))) {
|
||||
return; //out of bounds
|
||||
}
|
||||
|
||||
ivec2 uv_xy = pos_xy;
|
||||
if (params.flip_x) {
|
||||
uv_xy.x = params.rect_size.x - pos_xy.x - 1;
|
||||
}
|
||||
if (params.flip_y) {
|
||||
uv_xy.y = params.rect_size.y - pos_xy.y - 1;
|
||||
}
|
||||
|
||||
#ifdef MODE_DYNAMIC_LIGHTING
|
||||
|
||||
{
|
||||
float z = params.z_base + imageLoad(depth, uv_xy).x * params.z_sign;
|
||||
|
||||
ivec3 pos = params.x_dir * (params.rect_pos.x + pos_xy.x) + params.y_dir * (params.rect_pos.y + pos_xy.y) + abs(params.z_dir) * int(z);
|
||||
|
||||
vec3 normal = imageLoad(source_normal, uv_xy).xyz * 2.0 - 1.0;
|
||||
normal = vec3(params.x_dir) * normal.x * mix(1.0, -1.0, params.flip_x) + vec3(params.y_dir) * normal.y * mix(1.0, -1.0, params.flip_y) - vec3(params.z_dir) * normal.z;
|
||||
|
||||
vec4 albedo = imageLoad(source_albedo, uv_xy);
|
||||
|
||||
//determine the position in space
|
||||
|
||||
vec3 accum = vec3(0.0);
|
||||
for (uint i = 0; i < params.light_count; i++) {
|
||||
|
||||
vec3 light;
|
||||
vec3 light_dir;
|
||||
if (!compute_light_at_pos(i, vec3(pos) * params.pos_multiplier, normal, light, light_dir)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
light *= albedo.rgb;
|
||||
|
||||
accum += max(0.0, dot(normal, -light_dir)) * light;
|
||||
}
|
||||
|
||||
accum += imageLoad(emission, uv_xy).xyz;
|
||||
|
||||
imageStore(emission, uv_xy, vec4(accum, albedo.a));
|
||||
imageStore(depth, uv_xy, vec4(z));
|
||||
}
|
||||
|
||||
#endif // MODE DYNAMIC LIGHTING
|
||||
|
||||
#ifdef MODE_DYNAMIC_SHRINK
|
||||
|
||||
{
|
||||
vec4 accum = vec4(0.0);
|
||||
float accum_z = 0.0;
|
||||
float count = 0.0;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ivec2 ofs = pos_xy * 2 + ivec2(i & 1, i >> 1) - params.prev_rect_ofs;
|
||||
if (any(lessThan(ofs, ivec2(0))) || any(greaterThanEqual(ofs, params.prev_rect_size))) {
|
||||
continue;
|
||||
}
|
||||
if (params.flip_x) {
|
||||
ofs.x = params.prev_rect_size.x - ofs.x - 1;
|
||||
}
|
||||
if (params.flip_y) {
|
||||
ofs.y = params.prev_rect_size.y - ofs.y - 1;
|
||||
}
|
||||
|
||||
vec4 light = imageLoad(source_light, ofs);
|
||||
if (light.a == 0.0) { //ignore empty
|
||||
continue;
|
||||
}
|
||||
accum += light;
|
||||
float z = imageLoad(source_depth, ofs).x;
|
||||
accum_z += z * 0.5; //shrink half too
|
||||
count += 1.0;
|
||||
}
|
||||
|
||||
if (params.on_mipmap) {
|
||||
accum.rgb /= mix(8.0, count, params.propagation);
|
||||
accum.a /= 8.0;
|
||||
} else {
|
||||
accum /= 4.0;
|
||||
}
|
||||
|
||||
if (count == 0.0) {
|
||||
accum_z = 0.0; //avoid nan
|
||||
} else {
|
||||
accum_z /= count;
|
||||
}
|
||||
|
||||
#ifdef MODE_DYNAMIC_SHRINK_WRITE
|
||||
|
||||
imageStore(light, uv_xy, accum);
|
||||
imageStore(depth, uv_xy, vec4(accum_z));
|
||||
#endif
|
||||
|
||||
#ifdef MODE_DYNAMIC_SHRINK_PLOT
|
||||
|
||||
if (accum.a < 0.001) {
|
||||
return; //do not blit if alpha is too low
|
||||
}
|
||||
|
||||
ivec3 pos = params.x_dir * (params.rect_pos.x + pos_xy.x) + params.y_dir * (params.rect_pos.y + pos_xy.y) + abs(params.z_dir) * int(accum_z);
|
||||
|
||||
float z_frac = fract(accum_z);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
ivec3 pos3d = pos + abs(params.z_dir) * i;
|
||||
if (any(lessThan(pos3d, ivec3(0))) || any(greaterThanEqual(pos3d, params.limits))) {
|
||||
//skip if offlimits
|
||||
continue;
|
||||
}
|
||||
vec4 color_blit = accum * (i == 0 ? 1.0 - z_frac : z_frac);
|
||||
vec4 color = imageLoad(color_texture, pos3d);
|
||||
color.rgb *= params.dynamic_range;
|
||||
|
||||
#if 0
|
||||
color.rgb = mix(color.rgb,color_blit.rgb,color_blit.a);
|
||||
color.a+=color_blit.a;
|
||||
#else
|
||||
|
||||
float sa = 1.0 - color_blit.a;
|
||||
vec4 result;
|
||||
result.a = color.a * sa + color_blit.a;
|
||||
if (result.a == 0.0) {
|
||||
result = vec4(0.0);
|
||||
} else {
|
||||
result.rgb = (color.rgb * color.a * sa + color_blit.rgb * color_blit.a) / result.a;
|
||||
color = result;
|
||||
}
|
||||
|
||||
#endif
|
||||
color.rgb /= params.dynamic_range;
|
||||
imageStore(color_texture, pos3d, color);
|
||||
//imageStore(color_texture,pos3d,vec4(1,1,1,1));
|
||||
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
//do not care about anisotropy for dynamic objects, just store full lit in all directions
|
||||
imageStore(aniso_pos_texture, pos3d, uvec4(0xFFFF));
|
||||
imageStore(aniso_neg_texture, pos3d, uvec4(0xFFFF));
|
||||
|
||||
#endif // ANISOTROPIC
|
||||
}
|
||||
#endif // MODE_DYNAMIC_SHRINK_PLOT
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // MODE DYNAMIC
|
||||
}
|
||||
208
servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl
Normal file
208
servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/* clang-format off */
|
||||
[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
struct CellData {
|
||||
uint position; // xyz 10 bits
|
||||
uint albedo; //rgb albedo
|
||||
uint emission; //rgb normalized with e as multiplier
|
||||
uint normal; //RGB normal encoded
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
layout(set = 0, binding = 1, std140) buffer CellDataBuffer {
|
||||
CellData data[];
|
||||
}
|
||||
cell_data;
|
||||
|
||||
layout(set = 0, binding = 2) uniform texture3D color_tex;
|
||||
|
||||
layout(set = 0, binding = 3) uniform sampler tex_sampler;
|
||||
|
||||
#ifdef USE_ANISOTROPY
|
||||
layout(set = 0, binding = 4) uniform texture3D aniso_pos_tex;
|
||||
layout(set = 0, binding = 5) uniform texture3D aniso_neg_tex;
|
||||
#endif
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
|
||||
mat4 projection;
|
||||
uint cell_offset;
|
||||
float dynamic_range;
|
||||
float alpha;
|
||||
uint level;
|
||||
ivec3 bounds;
|
||||
uint pad;
|
||||
}
|
||||
params;
|
||||
|
||||
layout(location = 0) out vec4 color_interp;
|
||||
|
||||
void main() {
|
||||
|
||||
const vec3 cube_triangles[36] = vec3[](
|
||||
vec3(-1.0f, -1.0f, -1.0f),
|
||||
vec3(-1.0f, -1.0f, 1.0f),
|
||||
vec3(-1.0f, 1.0f, 1.0f),
|
||||
vec3(1.0f, 1.0f, -1.0f),
|
||||
vec3(-1.0f, -1.0f, -1.0f),
|
||||
vec3(-1.0f, 1.0f, -1.0f),
|
||||
vec3(1.0f, -1.0f, 1.0f),
|
||||
vec3(-1.0f, -1.0f, -1.0f),
|
||||
vec3(1.0f, -1.0f, -1.0f),
|
||||
vec3(1.0f, 1.0f, -1.0f),
|
||||
vec3(1.0f, -1.0f, -1.0f),
|
||||
vec3(-1.0f, -1.0f, -1.0f),
|
||||
vec3(-1.0f, -1.0f, -1.0f),
|
||||
vec3(-1.0f, 1.0f, 1.0f),
|
||||
vec3(-1.0f, 1.0f, -1.0f),
|
||||
vec3(1.0f, -1.0f, 1.0f),
|
||||
vec3(-1.0f, -1.0f, 1.0f),
|
||||
vec3(-1.0f, -1.0f, -1.0f),
|
||||
vec3(-1.0f, 1.0f, 1.0f),
|
||||
vec3(-1.0f, -1.0f, 1.0f),
|
||||
vec3(1.0f, -1.0f, 1.0f),
|
||||
vec3(1.0f, 1.0f, 1.0f),
|
||||
vec3(1.0f, -1.0f, -1.0f),
|
||||
vec3(1.0f, 1.0f, -1.0f),
|
||||
vec3(1.0f, -1.0f, -1.0f),
|
||||
vec3(1.0f, 1.0f, 1.0f),
|
||||
vec3(1.0f, -1.0f, 1.0f),
|
||||
vec3(1.0f, 1.0f, 1.0f),
|
||||
vec3(1.0f, 1.0f, -1.0f),
|
||||
vec3(-1.0f, 1.0f, -1.0f),
|
||||
vec3(1.0f, 1.0f, 1.0f),
|
||||
vec3(-1.0f, 1.0f, -1.0f),
|
||||
vec3(-1.0f, 1.0f, 1.0f),
|
||||
vec3(1.0f, 1.0f, 1.0f),
|
||||
vec3(-1.0f, 1.0f, 1.0f),
|
||||
vec3(1.0f, -1.0f, 1.0f));
|
||||
|
||||
vec3 vertex = cube_triangles[gl_VertexIndex] * 0.5 + 0.5;
|
||||
#ifdef MODE_DEBUG_LIGHT_FULL
|
||||
uvec3 posu = uvec3(gl_InstanceIndex % params.bounds.x, (gl_InstanceIndex / params.bounds.x) % params.bounds.y, gl_InstanceIndex / (params.bounds.y * params.bounds.x));
|
||||
#else
|
||||
uint cell_index = gl_InstanceIndex + params.cell_offset;
|
||||
|
||||
uvec3 posu = uvec3(cell_data.data[cell_index].position & 0x7FF, (cell_data.data[cell_index].position >> 11) & 0x3FF, cell_data.data[cell_index].position >> 21);
|
||||
#endif
|
||||
|
||||
#ifdef MODE_DEBUG_EMISSION
|
||||
color_interp.xyz = vec3(uvec3(cell_data.data[cell_index].emission & 0x1ff, (cell_data.data[cell_index].emission >> 9) & 0x1ff, (cell_data.data[cell_index].emission >> 18) & 0x1ff)) * pow(2.0, float(cell_data.data[cell_index].emission >> 27) - 15.0 - 9.0);
|
||||
#endif
|
||||
|
||||
#ifdef MODE_DEBUG_COLOR
|
||||
color_interp.xyz = unpackUnorm4x8(cell_data.data[cell_index].albedo).xyz;
|
||||
#endif
|
||||
|
||||
#ifdef MODE_DEBUG_LIGHT
|
||||
|
||||
#ifdef USE_ANISOTROPY
|
||||
|
||||
#define POS_X 0
|
||||
#define POS_Y 1
|
||||
#define POS_Z 2
|
||||
#define NEG_X 3
|
||||
#define NEG_Y 4
|
||||
#define NEG_Z 5
|
||||
|
||||
const uint triangle_aniso[12] = uint[](
|
||||
NEG_X,
|
||||
NEG_Z,
|
||||
NEG_Y,
|
||||
NEG_Z,
|
||||
NEG_X,
|
||||
NEG_Y,
|
||||
POS_Z,
|
||||
POS_X,
|
||||
POS_X,
|
||||
POS_Y,
|
||||
POS_Y,
|
||||
POS_Z);
|
||||
|
||||
color_interp.xyz = texelFetch(sampler3D(color_tex, tex_sampler), ivec3(posu), int(params.level)).xyz * params.dynamic_range;
|
||||
vec3 aniso_pos = texelFetch(sampler3D(aniso_pos_tex, tex_sampler), ivec3(posu), int(params.level)).xyz;
|
||||
vec3 aniso_neg = texelFetch(sampler3D(aniso_neg_tex, tex_sampler), ivec3(posu), int(params.level)).xyz;
|
||||
uint side = triangle_aniso[gl_VertexIndex / 3];
|
||||
|
||||
float strength = 0.0;
|
||||
switch (side) {
|
||||
case POS_X: strength = aniso_pos.x; break;
|
||||
case POS_Y: strength = aniso_pos.y; break;
|
||||
case POS_Z: strength = aniso_pos.z; break;
|
||||
case NEG_X: strength = aniso_neg.x; break;
|
||||
case NEG_Y: strength = aniso_neg.y; break;
|
||||
case NEG_Z: strength = aniso_neg.z; break;
|
||||
}
|
||||
|
||||
color_interp.xyz *= strength;
|
||||
|
||||
#else
|
||||
color_interp = texelFetch(sampler3D(color_tex, tex_sampler), ivec3(posu), int(params.level));
|
||||
color_interp.xyz *params.dynamic_range;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
float scale = (1 << params.level);
|
||||
|
||||
gl_Position = params.projection * vec4((vec3(posu) + vertex) * scale, 1.0);
|
||||
|
||||
#ifdef MODE_DEBUG_LIGHT_FULL
|
||||
if (color_interp.a == 0.0) {
|
||||
gl_Position = vec4(0.0); //force clip and not draw
|
||||
}
|
||||
#else
|
||||
color_interp.a = params.alpha;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
[fragment]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(location = 0) in vec4 color_interp;
|
||||
/* clang-format on */
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
void main() {
|
||||
|
||||
frag_color = color_interp;
|
||||
|
||||
#ifdef MODE_DEBUG_LIGHT_FULL
|
||||
|
||||
//there really is no alpha, so use dither
|
||||
|
||||
int x = int(gl_FragCoord.x) % 4;
|
||||
int y = int(gl_FragCoord.y) % 4;
|
||||
int index = x + y * 4;
|
||||
float limit = 0.0;
|
||||
if (x < 8) {
|
||||
if (index == 0) limit = 0.0625;
|
||||
if (index == 1) limit = 0.5625;
|
||||
if (index == 2) limit = 0.1875;
|
||||
if (index == 3) limit = 0.6875;
|
||||
if (index == 4) limit = 0.8125;
|
||||
if (index == 5) limit = 0.3125;
|
||||
if (index == 6) limit = 0.9375;
|
||||
if (index == 7) limit = 0.4375;
|
||||
if (index == 8) limit = 0.25;
|
||||
if (index == 9) limit = 0.75;
|
||||
if (index == 10) limit = 0.125;
|
||||
if (index == 11) limit = 0.625;
|
||||
if (index == 12) limit = 1.0;
|
||||
if (index == 13) limit = 0.5;
|
||||
if (index == 14) limit = 0.875;
|
||||
if (index == 15) limit = 0.375;
|
||||
}
|
||||
if (frag_color.a < limit) {
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
187
servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl
Normal file
187
servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/* clang-format off */
|
||||
[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
|
||||
/* clang-format on */
|
||||
|
||||
#define MAX_DISTANCE 100000
|
||||
|
||||
#define NO_CHILDREN 0xFFFFFFFF
|
||||
#define GREY_VEC vec3(0.33333, 0.33333, 0.33333)
|
||||
|
||||
struct CellChildren {
|
||||
uint children[8];
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer {
|
||||
CellChildren data[];
|
||||
}
|
||||
cell_children;
|
||||
|
||||
struct CellData {
|
||||
uint position; // xyz 10 bits
|
||||
uint albedo; //rgb albedo
|
||||
uint emission; //rgb normalized with e as multiplier
|
||||
uint normal; //RGB normal encoded
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 2, std430) buffer CellDataBuffer {
|
||||
CellData data[];
|
||||
}
|
||||
cell_data;
|
||||
|
||||
layout(r8ui, set = 0, binding = 3) uniform restrict writeonly uimage3D sdf_tex;
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
uint offset;
|
||||
uint end;
|
||||
uint pad0;
|
||||
uint pad1;
|
||||
}
|
||||
params;
|
||||
|
||||
void main() {
|
||||
|
||||
vec3 pos = vec3(gl_GlobalInvocationID);
|
||||
float closest_dist = 100000.0;
|
||||
|
||||
for (uint i = params.offset; i < params.end; i++) {
|
||||
vec3 posu = vec3(uvec3(cell_data.data[i].position & 0x7FF, (cell_data.data[i].position >> 11) & 0x3FF, cell_data.data[i].position >> 21));
|
||||
float dist = length(pos - posu);
|
||||
if (dist < closest_dist) {
|
||||
closest_dist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
uint dist_8;
|
||||
|
||||
if (closest_dist < 0.0001) { // same cell
|
||||
dist_8 = 0; //equals to -1
|
||||
} else {
|
||||
dist_8 = clamp(uint(closest_dist), 0, 254) + 1; //conservative, 0 is 1, so <1 is considered solid
|
||||
}
|
||||
|
||||
imageStore(sdf_tex, ivec3(gl_GlobalInvocationID), uvec4(dist_8));
|
||||
//imageStore(sdf_tex,pos,uvec4(pos*2,0));
|
||||
}
|
||||
|
||||
#if 0
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
|
||||
ivec3 limits;
|
||||
uint stack_size;
|
||||
} params;
|
||||
|
||||
float distance_to_aabb(ivec3 pos, ivec3 aabb_pos, ivec3 aabb_size) {
|
||||
|
||||
vec3 delta = vec3(max(ivec3(0), max(aabb_pos - pos, pos - (aabb_pos + aabb_size - ivec3(1)))));
|
||||
return length(delta);
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
ivec3 pos = ivec3(gl_GlobalInvocationID);
|
||||
|
||||
uint stack[10] = uint[](0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
uint stack_indices[10] = uint[](0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
ivec3 stack_positions[10] = ivec3[](ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0));
|
||||
|
||||
const uint cell_orders[8] = uint[](
|
||||
0x11f58d1,
|
||||
0xe2e70a,
|
||||
0xd47463,
|
||||
0xbb829c,
|
||||
0x8d11f5,
|
||||
0x70ae2e,
|
||||
0x463d47,
|
||||
0x29cbb8);
|
||||
|
||||
bool cell_found = false;
|
||||
bool cell_found_exact = false;
|
||||
ivec3 closest_cell_pos;
|
||||
float closest_distance = MAX_DISTANCE;
|
||||
int stack_pos = 0;
|
||||
|
||||
while (true) {
|
||||
|
||||
uint index = stack_indices[stack_pos] >> 24;
|
||||
|
||||
if (index == 8) {
|
||||
//go up
|
||||
if (stack_pos == 0) {
|
||||
break; //done going through octree
|
||||
}
|
||||
stack_pos--;
|
||||
continue;
|
||||
}
|
||||
|
||||
stack_indices[stack_pos] = (stack_indices[stack_pos] & ((1 << 24) - 1)) | ((index + 1) << 24);
|
||||
|
||||
uint cell_index = (stack_indices[stack_pos] >> (index * 3)) & 0x7;
|
||||
uint child_cell = cell_children.data[stack[stack_pos]].children[cell_index];
|
||||
|
||||
if (child_cell == NO_CHILDREN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ivec3 child_cell_size = params.limits >> (stack_pos + 1);
|
||||
ivec3 child_cell_pos = stack_positions[stack_pos];
|
||||
|
||||
child_cell_pos += mix(ivec3(0), child_cell_size, bvec3(uvec3(index & 1, index & 2, index & 4) != uvec3(0)));
|
||||
|
||||
bool is_leaf = stack_pos == (params.stack_size - 2);
|
||||
|
||||
if (child_cell_pos == pos && is_leaf) {
|
||||
//we may actually end up in the exact cell.
|
||||
//if this happens, just abort
|
||||
cell_found_exact = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cell_found) {
|
||||
//discard by distance
|
||||
float distance = distance_to_aabb(pos, child_cell_pos, child_cell_size);
|
||||
if (distance >= closest_distance) {
|
||||
continue; //pointless, just test next child
|
||||
} else if (is_leaf) {
|
||||
//closer than what we have AND end of stack, save and continue
|
||||
closest_cell_pos = child_cell_pos;
|
||||
closest_distance = distance;
|
||||
continue;
|
||||
}
|
||||
} else if (is_leaf) {
|
||||
//first solid cell we find, save and continue
|
||||
closest_distance = distance_to_aabb(pos, child_cell_pos, child_cell_size);
|
||||
closest_cell_pos = child_cell_pos;
|
||||
cell_found = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
bvec3 direction = greaterThan((pos - (child_cell_pos + (child_cell_size >> 1))), ivec3(0));
|
||||
uint cell_order = 0;
|
||||
cell_order |= mix(0, 1, direction.x);
|
||||
cell_order |= mix(0, 2, direction.y);
|
||||
cell_order |= mix(0, 4, direction.z);
|
||||
|
||||
stack[stack_pos + 1] = child_cell;
|
||||
stack_indices[stack_pos + 1] = cell_orders[cell_order]; //start counting
|
||||
stack_positions[stack_pos + 1] = child_cell_pos;
|
||||
stack_pos++; //go up stack
|
||||
}
|
||||
|
||||
uint dist_8;
|
||||
|
||||
if (cell_found_exact) {
|
||||
dist_8 = 0; //equals to -1
|
||||
} else {
|
||||
float closest_distance = length(vec3(pos - closest_cell_pos));
|
||||
dist_8 = clamp(uint(closest_distance), 0, 254) + 1; //conservative, 0 is 1, so <1 is considered solid
|
||||
}
|
||||
|
||||
imageStore(sdf_tex, pos, uvec4(dist_8));
|
||||
}
|
||||
#endif
|
||||
335
servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl
Normal file
335
servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl
Normal file
|
|
@ -0,0 +1,335 @@
|
|||
/* clang-format off */
|
||||
[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
|
||||
/* clang-format on */
|
||||
|
||||
#define NO_CHILDREN 0xFFFFFFFF
|
||||
#define GREY_VEC vec3(0.33333, 0.33333, 0.33333)
|
||||
|
||||
struct CellChildren {
|
||||
uint children[8];
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer {
|
||||
CellChildren data[];
|
||||
}
|
||||
cell_children;
|
||||
|
||||
struct CellData {
|
||||
uint position; // xyz 10 bits
|
||||
uint albedo; //rgb albedo
|
||||
uint emission; //rgb normalized with e as multiplier
|
||||
uint normal; //RGB normal encoded
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 2, std430) buffer CellDataBuffer {
|
||||
CellData data[];
|
||||
}
|
||||
cell_data;
|
||||
|
||||
#define LIGHT_TYPE_DIRECTIONAL 0
|
||||
#define LIGHT_TYPE_OMNI 1
|
||||
#define LIGHT_TYPE_SPOT 2
|
||||
|
||||
#ifdef MODE_COMPUTE_LIGHT
|
||||
|
||||
struct Light {
|
||||
uint type;
|
||||
float energy;
|
||||
float radius;
|
||||
float attenuation;
|
||||
|
||||
vec3 color;
|
||||
float spot_angle_radians;
|
||||
|
||||
vec3 position;
|
||||
float spot_attenuation;
|
||||
|
||||
vec3 direction;
|
||||
bool has_shadow;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 3, std140) uniform Lights {
|
||||
Light data[MAX_LIGHTS];
|
||||
}
|
||||
lights;
|
||||
|
||||
#endif
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform Params {
|
||||
ivec3 limits;
|
||||
uint stack_size;
|
||||
|
||||
float emission_scale;
|
||||
float propagation;
|
||||
float dynamic_range;
|
||||
|
||||
uint light_count;
|
||||
uint cell_offset;
|
||||
uint cell_count;
|
||||
uint pad[2];
|
||||
}
|
||||
params;
|
||||
|
||||
layout(set = 0, binding = 4, std140) uniform Outputs {
|
||||
vec4 data[];
|
||||
}
|
||||
output;
|
||||
|
||||
#ifdef MODE_COMPUTE_LIGHT
|
||||
|
||||
uint raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {
|
||||
|
||||
uint result = NO_CHILDREN;
|
||||
|
||||
ivec3 size = ivec3(max(max(params.limits.x, params.limits.y), params.limits.z));
|
||||
|
||||
while (distance > -distance_adv) { //use this to avoid precision errors
|
||||
|
||||
uint cell = 0;
|
||||
|
||||
ivec3 pos = ivec3(from);
|
||||
|
||||
if (all(greaterThanEqual(pos, ivec3(0))) && all(lessThan(pos, size))) {
|
||||
|
||||
ivec3 ofs = ivec3(0);
|
||||
ivec3 half_size = size / 2;
|
||||
|
||||
for (int i = 0; i < params.stack_size - 1; i++) {
|
||||
|
||||
bvec3 greater = greaterThanEqual(pos, ofs + half_size);
|
||||
|
||||
ofs += mix(ivec3(0), half_size, greater);
|
||||
|
||||
uint child = 0; //wonder if this can be done faster
|
||||
if (greater.x) {
|
||||
child |= 1;
|
||||
}
|
||||
if (greater.y) {
|
||||
child |= 2;
|
||||
}
|
||||
if (greater.z) {
|
||||
child |= 4;
|
||||
}
|
||||
|
||||
cell = cell_children.data[cell].children[child];
|
||||
if (cell == NO_CHILDREN)
|
||||
break;
|
||||
|
||||
half_size >>= ivec3(1);
|
||||
}
|
||||
|
||||
if (cell != NO_CHILDREN) {
|
||||
return cell; //found cell!
|
||||
}
|
||||
}
|
||||
|
||||
from += direction * distance_adv;
|
||||
distance -= distance_adv;
|
||||
}
|
||||
|
||||
return NO_CHILDREN;
|
||||
}
|
||||
|
||||
bool compute_light_vector(uint light, uint cell, vec3 pos, out float attenuation, out vec3 light_pos) {
|
||||
|
||||
if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) {
|
||||
|
||||
light_pos = pos - lights.data[light].direction * length(vec3(params.limits));
|
||||
attenuation = 1.0;
|
||||
|
||||
} else {
|
||||
|
||||
light_pos = lights.data[light].position;
|
||||
float distance = length(pos - light_pos);
|
||||
if (distance >= lights.data[light].radius) {
|
||||
return false;
|
||||
}
|
||||
|
||||
attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation);
|
||||
|
||||
if (lights.data[light].type == LIGHT_TYPE_SPOT) {
|
||||
|
||||
vec3 rel = normalize(pos - light_pos);
|
||||
float angle = acos(dot(rel, lights.data[light].direction));
|
||||
if (angle > lights.data[light].spot_angle_radians) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1);
|
||||
attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float get_normal_advance(vec3 p_normal) {
|
||||
|
||||
vec3 normal = p_normal;
|
||||
vec3 unorm = abs(normal);
|
||||
|
||||
if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) {
|
||||
// x code
|
||||
unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0);
|
||||
} else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) {
|
||||
// y code
|
||||
unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0);
|
||||
} else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) {
|
||||
// z code
|
||||
unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0);
|
||||
} else {
|
||||
// oh-no we messed up code
|
||||
// has to be
|
||||
unorm = vec3(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
return 1.0 / dot(normal, unorm);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
|
||||
uint cell_index = gl_GlobalInvocationID.x;
|
||||
if (cell_index >= params.cell_count) {
|
||||
return;
|
||||
}
|
||||
cell_index += params.cell_offset;
|
||||
|
||||
uvec3 posu = uvec3(cell_data.data[cell_index].position & 0x7FF, (cell_data.data[cell_index].position >> 11) & 0x3FF, cell_data.data[cell_index].position >> 21);
|
||||
vec4 albedo = unpackUnorm4x8(cell_data.data[cell_index].albedo);
|
||||
|
||||
#ifdef MODE_COMPUTE_LIGHT
|
||||
|
||||
vec3 pos = vec3(posu) + vec3(0.5);
|
||||
|
||||
vec3 emission = vec3(ivec3(cell_data.data[cell_index].emission & 0x3FF, (cell_data.data[cell_index].emission >> 10) & 0x7FF, cell_data.data[cell_index].emission >> 21)) * params.emission_scale;
|
||||
vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal);
|
||||
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
vec3 accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
|
||||
const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0));
|
||||
#else
|
||||
vec3 accum = vec3(0.0);
|
||||
#endif
|
||||
|
||||
for (uint i = 0; i < params.light_count; i++) {
|
||||
|
||||
float attenuation;
|
||||
vec3 light_pos;
|
||||
|
||||
if (!compute_light_vector(i, cell_index, pos, attenuation, light_pos)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
vec3 light_dir = pos - light_pos;
|
||||
float distance = length(light_dir);
|
||||
light_dir = normalize(light_dir);
|
||||
|
||||
if (length(normal.xyz) > 0.2 && dot(normal.xyz, light_dir) >= 0) {
|
||||
continue; //not facing the light
|
||||
}
|
||||
|
||||
if (lights.data[i].has_shadow) {
|
||||
|
||||
float distance_adv = get_normal_advance(light_dir);
|
||||
|
||||
distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always
|
||||
|
||||
vec3 from = pos - light_dir * distance; //approximate
|
||||
from -= sign(light_dir) * 0.45; //go near the edge towards the light direction to avoid self occlusion
|
||||
|
||||
uint result = raymarch(distance, distance_adv, from, light_dir);
|
||||
|
||||
if (result != cell_index) {
|
||||
continue; //was occluded
|
||||
}
|
||||
}
|
||||
|
||||
vec3 light = lights.data[i].color * albedo.rgb * attenuation * lights.data[i].energy;
|
||||
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
for (uint j = 0; j < 6; j++) {
|
||||
accum[j] += max(0.0, dot(accum_dir, -light_dir)) * light + emission;
|
||||
}
|
||||
#else
|
||||
if (length(normal.xyz) > 0.2) {
|
||||
accum += max(0.0, dot(normal.xyz, -light_dir)) * light + emission;
|
||||
} else {
|
||||
//all directions
|
||||
accum += light + emission;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
|
||||
output.data[cell_index * 6 + 0] = vec4(accum[0], 0.0);
|
||||
output.data[cell_index * 6 + 1] = vec4(accum[1], 0.0);
|
||||
output.data[cell_index * 6 + 2] = vec4(accum[2], 0.0);
|
||||
output.data[cell_index * 6 + 3] = vec4(accum[3], 0.0);
|
||||
output.data[cell_index * 6 + 4] = vec4(accum[4], 0.0);
|
||||
output.data[cell_index * 6 + 5] = vec4(accum[5], 0.0);
|
||||
#else
|
||||
output.data[cell_index] = vec4(accum, 0.0);
|
||||
|
||||
#endif
|
||||
|
||||
#endif //MODE_COMPUTE_LIGHT
|
||||
|
||||
#ifdef MODE_UPDATE_MIPMAPS
|
||||
|
||||
{
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
vec3 light_accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
|
||||
#else
|
||||
vec3 light_accum = vec3(0.0);
|
||||
#endif
|
||||
float count = 0.0;
|
||||
for (uint i = 0; i < 8; i++) {
|
||||
uint child_index = cell_children.data[cell_index].children[i];
|
||||
if (child_index == NO_CHILDREN) {
|
||||
continue;
|
||||
}
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
light_accum[1] += output.data[child_index * 6 + 0].rgb;
|
||||
light_accum[2] += output.data[child_index * 6 + 1].rgb;
|
||||
light_accum[3] += output.data[child_index * 6 + 2].rgb;
|
||||
light_accum[4] += output.data[child_index * 6 + 3].rgb;
|
||||
light_accum[5] += output.data[child_index * 6 + 4].rgb;
|
||||
light_accum[6] += output.data[child_index * 6 + 5].rgb;
|
||||
|
||||
#else
|
||||
light_accum += output.data[child_index].rgb;
|
||||
|
||||
#endif
|
||||
|
||||
count += 1.0;
|
||||
}
|
||||
|
||||
float divisor = mix(8.0, count, params.propagation);
|
||||
#ifdef MODE_ANISOTROPIC
|
||||
output.data[cell_index * 6 + 0] = vec4(light_accum[0] / divisor, 0.0);
|
||||
output.data[cell_index * 6 + 1] = vec4(light_accum[1] / divisor, 0.0);
|
||||
output.data[cell_index * 6 + 2] = vec4(light_accum[2] / divisor, 0.0);
|
||||
output.data[cell_index * 6 + 3] = vec4(light_accum[3] / divisor, 0.0);
|
||||
output.data[cell_index * 6 + 4] = vec4(light_accum[4] / divisor, 0.0);
|
||||
output.data[cell_index * 6 + 5] = vec4(light_accum[5] / divisor, 0.0);
|
||||
|
||||
#else
|
||||
output.data[cell_index] = vec4(light_accum / divisor, 0.0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MODE_WRITE_TEXTURE
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/* clang-format off */
|
||||
[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
#define BLOCK_SIZE 8
|
||||
|
||||
layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in;
|
||||
/* clang-format on */
|
||||
|
||||
shared float tmp_data[BLOCK_SIZE * BLOCK_SIZE];
|
||||
|
||||
#ifdef READ_TEXTURE
|
||||
|
||||
//use for main texture
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_texture;
|
||||
|
||||
#else
|
||||
|
||||
//use for intermediate textures
|
||||
layout(r32f, set = 0, binding = 0) uniform restrict readonly image2D source_luminance;
|
||||
|
||||
#endif
|
||||
|
||||
layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_luminance;
|
||||
|
||||
#ifdef WRITE_LUMINANCE
|
||||
layout(set = 2, binding = 0) uniform sampler2D prev_luminance;
|
||||
#endif
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
ivec2 source_size;
|
||||
float max_luminance;
|
||||
float min_luminance;
|
||||
float exposure_adjust;
|
||||
float pad[3];
|
||||
}
|
||||
params;
|
||||
|
||||
void main() {
|
||||
|
||||
uint t = gl_LocalInvocationID.y * BLOCK_SIZE + gl_LocalInvocationID.x;
|
||||
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
if (any(lessThan(pos, params.source_size))) {
|
||||
|
||||
#ifdef READ_TEXTURE
|
||||
vec3 v = texelFetch(source_texture, pos, 0).rgb;
|
||||
tmp_data[t] = max(v.r, max(v.g, v.b));
|
||||
#else
|
||||
tmp_data[t] = imageLoad(source_luminance, pos).r;
|
||||
#endif
|
||||
} else {
|
||||
tmp_data[t] = 0.0;
|
||||
}
|
||||
|
||||
groupMemoryBarrier();
|
||||
barrier();
|
||||
|
||||
uint size = (BLOCK_SIZE * BLOCK_SIZE) >> 1;
|
||||
|
||||
do {
|
||||
if (t < size) {
|
||||
tmp_data[t] += tmp_data[t + size];
|
||||
}
|
||||
groupMemoryBarrier();
|
||||
barrier();
|
||||
|
||||
size >>= 1;
|
||||
|
||||
} while (size >= 1);
|
||||
|
||||
if (t == 0) {
|
||||
//compute rect size
|
||||
ivec2 rect_size = min(params.source_size - pos, ivec2(BLOCK_SIZE));
|
||||
float avg = tmp_data[0] / float(rect_size.x * rect_size.y);
|
||||
//float avg = tmp_data[0] / float(BLOCK_SIZE*BLOCK_SIZE);
|
||||
pos /= ivec2(BLOCK_SIZE);
|
||||
#ifdef WRITE_LUMINANCE
|
||||
float prev_lum = texelFetch(prev_luminance, ivec2(0, 0), 0).r; //1 pixel previous exposure
|
||||
avg = clamp(prev_lum + (avg - prev_lum) * params.exposure_adjust, params.min_luminance, params.max_luminance);
|
||||
#endif
|
||||
imageStore(dest_luminance, pos, vec4(avg));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/* clang-format off */
|
||||
[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
/* clang-format on */
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_normal;
|
||||
layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_roughness;
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
ivec2 screen_size;
|
||||
float curve;
|
||||
uint pad;
|
||||
}
|
||||
params;
|
||||
|
||||
#define HALF_PI 1.5707963267948966
|
||||
|
||||
void main() {
|
||||
|
||||
// Pixel being shaded
|
||||
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
|
||||
if (any(greaterThan(pos, params.screen_size))) { //too large, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 normal_accum = vec3(0.0);
|
||||
float accum = 0.0;
|
||||
for (int i = 0; i <= 1; i++) {
|
||||
for (int j = 0; j <= 1; j++) {
|
||||
normal_accum += normalize(texelFetch(source_normal, pos + ivec2(i, j), 0).xyz * 2.0 - 1.0);
|
||||
accum += 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
normal_accum /= accum;
|
||||
|
||||
float r = length(normal_accum);
|
||||
|
||||
float limit;
|
||||
|
||||
if (r < 1.0) {
|
||||
float threshold = 0.4;
|
||||
|
||||
/*
|
||||
//Formula from Filament, does not make sense to me.
|
||||
|
||||
float r2 = r * r;
|
||||
float kappa = (3.0f * r - r * r2) / (1.0f - r2);
|
||||
float variance = 0.25f / kappa;
|
||||
limit = sqrt(min(2.0f * variance, threshold * threshold));
|
||||
//*/
|
||||
/*
|
||||
//Formula based on probability distribution graph
|
||||
|
||||
float width = acos(max(0.0,r)); // convert to angle (width)
|
||||
float roughness = pow(width,1.7)*0.854492; //approximate (crappy) formula to convert to roughness
|
||||
limit = min(sqrt(roughness), threshold); //convert to perceptual roughness and apply threshold
|
||||
//*/
|
||||
|
||||
limit = min(sqrt(pow(acos(max(0.0, r)) / HALF_PI, params.curve)), threshold); //convert to perceptual roughness and apply threshold
|
||||
|
||||
//limit = 0.5;
|
||||
} else {
|
||||
limit = 0.0;
|
||||
}
|
||||
|
||||
imageStore(dest_roughness, pos, vec4(limit));
|
||||
}
|
||||
1718
servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
Normal file
1718
servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl
Normal file
File diff suppressed because it is too large
Load diff
266
servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
Normal file
266
servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
#define M_PI 3.14159265359
|
||||
#define ROUGHNESS_MAX_LOD 5
|
||||
|
||||
layout(push_constant, binding = 0, std430) uniform DrawCall {
|
||||
uint instance_index;
|
||||
uint pad[3]; //16 bits minimum size
|
||||
}
|
||||
draw_call;
|
||||
|
||||
/* Set 0 Scene data that never changes, ever */
|
||||
|
||||
#define SAMPLER_NEAREST_CLAMP 0
|
||||
#define SAMPLER_LINEAR_CLAMP 1
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP 3
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_CLAMP 4
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_CLAMP 5
|
||||
#define SAMPLER_NEAREST_REPEAT 6
|
||||
#define SAMPLER_LINEAR_REPEAT 7
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT 8
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT 9
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
|
||||
|
||||
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
|
||||
|
||||
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
|
||||
|
||||
layout(set = 0, binding = 3, std140) uniform SceneData {
|
||||
|
||||
mat4 projection_matrix;
|
||||
mat4 inv_projection_matrix;
|
||||
|
||||
mat4 camera_matrix;
|
||||
mat4 inv_camera_matrix;
|
||||
|
||||
vec2 viewport_size;
|
||||
vec2 screen_pixel_size;
|
||||
|
||||
//used for shadow mapping only
|
||||
float z_offset;
|
||||
float z_slope_scale;
|
||||
|
||||
float time;
|
||||
float reflection_multiplier; // one normally, zero when rendering reflections
|
||||
|
||||
vec4 ambient_light_color_energy;
|
||||
|
||||
float ambient_color_sky_mix;
|
||||
bool use_ambient_light;
|
||||
bool use_ambient_cubemap;
|
||||
bool use_reflection_cubemap;
|
||||
|
||||
mat3 radiance_inverse_xform;
|
||||
|
||||
vec2 shadow_atlas_pixel_size;
|
||||
vec2 directional_shadow_pixel_size;
|
||||
|
||||
uint directional_light_count;
|
||||
float dual_paraboloid_side;
|
||||
float z_far;
|
||||
float z_near;
|
||||
|
||||
bool ssao_enabled;
|
||||
float ssao_light_affect;
|
||||
float ssao_ao_affect;
|
||||
bool roughness_limiter_enabled;
|
||||
|
||||
vec4 ao_color;
|
||||
|
||||
#if 0
|
||||
vec4 ambient_light_color;
|
||||
vec4 bg_color;
|
||||
|
||||
vec4 fog_color_enabled;
|
||||
vec4 fog_sun_color_amount;
|
||||
|
||||
float ambient_energy;
|
||||
float bg_energy;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
vec2 shadow_atlas_pixel_size;
|
||||
vec2 directional_shadow_pixel_size;
|
||||
|
||||
float z_far;
|
||||
|
||||
float subsurface_scatter_width;
|
||||
float ambient_occlusion_affect_light;
|
||||
float ambient_occlusion_affect_ao_channel;
|
||||
float opaque_prepass_threshold;
|
||||
|
||||
bool fog_depth_enabled;
|
||||
float fog_depth_begin;
|
||||
float fog_depth_end;
|
||||
float fog_density;
|
||||
float fog_depth_curve;
|
||||
bool fog_transmit_enabled;
|
||||
float fog_transmit_curve;
|
||||
bool fog_height_enabled;
|
||||
float fog_height_min;
|
||||
float fog_height_max;
|
||||
float fog_height_curve;
|
||||
#endif
|
||||
}
|
||||
scene_data;
|
||||
|
||||
#define INSTANCE_FLAGS_FORWARD_MASK 0x7
|
||||
#define INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT 3
|
||||
#define INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT 6
|
||||
#define INSTANCE_FLAGS_FORWARD_DECAL_SHIFT 9
|
||||
|
||||
#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
|
||||
#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
|
||||
#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
|
||||
#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15)
|
||||
#define INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT 16
|
||||
//3 bits of stride
|
||||
#define INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK 0x7
|
||||
|
||||
#define INSTANCE_FLAGS_SKELETON (1 << 19)
|
||||
|
||||
struct InstanceData {
|
||||
mat4 transform;
|
||||
mat4 normal_transform;
|
||||
uint flags;
|
||||
uint instance_ofs; //instance_offset in instancing/skeleton buffer
|
||||
uint gi_offset; //GI information when using lightmapping (VCT or lightmap)
|
||||
uint layer_mask;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 4, std430) buffer Instances {
|
||||
InstanceData data[];
|
||||
}
|
||||
instances;
|
||||
|
||||
struct LightData { //this structure needs to be 128 bits
|
||||
vec3 position;
|
||||
float inv_radius;
|
||||
vec3 direction;
|
||||
uint attenuation_energy; //attenuation
|
||||
uint color_specular; //rgb color, a specular (8 bit unorm)
|
||||
uint cone_attenuation_angle; // attenuation and angle, (16bit float)
|
||||
uint mask;
|
||||
uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm)
|
||||
vec4 atlas_rect; //used for shadow atlas uv on omni, and for projection atlas on spot
|
||||
mat4 shadow_matrix;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 5, std140) uniform Lights {
|
||||
LightData data[MAX_LIGHT_DATA_STRUCTS];
|
||||
}
|
||||
lights;
|
||||
|
||||
struct ReflectionData {
|
||||
|
||||
vec3 box_extents;
|
||||
float index;
|
||||
vec3 box_offset;
|
||||
uint mask;
|
||||
vec4 params; // intensity, 0, interior , boxproject
|
||||
vec4 ambient; // ambient color, energy
|
||||
mat4 local_matrix; // up to here for spot and omni, rest is for directional
|
||||
// notes: for ambientblend, use distance to edge to blend between already existing global environment
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 6, std140) uniform ReflectionProbeData {
|
||||
ReflectionData data[MAX_REFLECTION_DATA_STRUCTS];
|
||||
}
|
||||
reflections;
|
||||
|
||||
struct DirectionalLightData {
|
||||
vec3 direction;
|
||||
float energy;
|
||||
vec3 color;
|
||||
float specular;
|
||||
vec3 shadow_color;
|
||||
uint mask;
|
||||
bool blend_splits;
|
||||
bool shadow_enabled;
|
||||
float fade_from;
|
||||
float fade_to;
|
||||
vec4 shadow_split_offsets;
|
||||
mat4 shadow_matrix1;
|
||||
mat4 shadow_matrix2;
|
||||
mat4 shadow_matrix3;
|
||||
mat4 shadow_matrix4;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 7, std140) uniform DirectionalLights {
|
||||
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
|
||||
}
|
||||
directional_lights;
|
||||
|
||||
struct GIProbeData {
|
||||
mat4 xform;
|
||||
vec3 bounds;
|
||||
float dynamic_range;
|
||||
|
||||
float bias;
|
||||
float normal_bias;
|
||||
bool blend_ambient;
|
||||
uint texture_slot;
|
||||
|
||||
float anisotropy_strength;
|
||||
float ambient_occlusion;
|
||||
float ambient_occlusion_size;
|
||||
uint pad2;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 8, std140) uniform GIProbes {
|
||||
GIProbeData data[MAX_GI_PROBES];
|
||||
}
|
||||
gi_probes;
|
||||
|
||||
layout(set = 0, binding = 9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TEXTURES];
|
||||
|
||||
#define CLUSTER_COUNTER_SHIFT 20
|
||||
#define CLUSTER_POINTER_MASK ((1 << CLUSTER_COUNTER_SHIFT) - 1)
|
||||
#define CLUSTER_COUNTER_MASK 0xfff
|
||||
|
||||
layout(set = 0, binding = 10) uniform utexture3D cluster_texture;
|
||||
|
||||
layout(set = 0, binding = 11, std430) buffer ClusterData {
|
||||
uint indices[];
|
||||
}
|
||||
cluster_data;
|
||||
|
||||
layout(set = 0, binding = 12) uniform texture2D directional_shadow_atlas;
|
||||
|
||||
// decal atlas
|
||||
|
||||
/* Set 1, Radiance */
|
||||
|
||||
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
|
||||
|
||||
layout(set = 1, binding = 0) uniform textureCubeArray radiance_cubemap;
|
||||
|
||||
#else
|
||||
|
||||
layout(set = 1, binding = 0) uniform textureCube radiance_cubemap;
|
||||
|
||||
#endif
|
||||
|
||||
/* Set 2, Reflection and Shadow Atlases (view dependant) */
|
||||
|
||||
layout(set = 2, binding = 0) uniform textureCubeArray reflection_atlas;
|
||||
|
||||
layout(set = 2, binding = 1) uniform texture2D shadow_atlas;
|
||||
|
||||
/* Set 1, Render Buffers */
|
||||
|
||||
layout(set = 3, binding = 0) uniform texture2D depth_buffer;
|
||||
layout(set = 3, binding = 1) uniform texture2D color_buffer;
|
||||
layout(set = 3, binding = 2) uniform texture2D normal_buffer;
|
||||
layout(set = 3, binding = 3) uniform texture2D roughness_buffer;
|
||||
layout(set = 3, binding = 4) uniform texture2D ao_buffer;
|
||||
|
||||
/* Set 4 Skeleton & Instancing (Multimesh) */
|
||||
|
||||
layout(set = 4, binding = 0, std430) buffer Transforms {
|
||||
vec4 data[];
|
||||
}
|
||||
transforms;
|
||||
|
||||
/* Set 5 User Material */
|
||||
181
servers/rendering/rasterizer_rd/shaders/sky.glsl
Normal file
181
servers/rendering/rasterizer_rd/shaders/sky.glsl
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
/* clang-format off */
|
||||
[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(location = 0) out vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
mat3 orientation;
|
||||
vec4 proj;
|
||||
vec4 position_multiplier;
|
||||
float time;
|
||||
}
|
||||
params;
|
||||
|
||||
void main() {
|
||||
|
||||
vec2 base_arr[4] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0), vec2(1.0, -1.0));
|
||||
uv_interp = base_arr[gl_VertexIndex];
|
||||
gl_Position = vec4(uv_interp, 1.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
[fragment]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
layout(location = 0) in vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
mat3 orientation;
|
||||
vec4 proj;
|
||||
vec4 position_multiplier;
|
||||
float time; //TODO consider adding vec2 screen res, and float radiance size
|
||||
}
|
||||
params;
|
||||
|
||||
#define SAMPLER_NEAREST_CLAMP 0
|
||||
#define SAMPLER_LINEAR_CLAMP 1
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP 3
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_CLAMP 4
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_CLAMP 5
|
||||
#define SAMPLER_NEAREST_REPEAT 6
|
||||
#define SAMPLER_LINEAR_REPEAT 7
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT 8
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT 9
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler material_samplers[12];
|
||||
|
||||
#ifdef USE_MATERIAL_UNIFORMS
|
||||
layout(set = 1, binding = 0, std140) uniform MaterialUniforms{
|
||||
/* clang-format off */
|
||||
|
||||
MATERIAL_UNIFORMS
|
||||
|
||||
/* clang-format on */
|
||||
} material;
|
||||
#endif
|
||||
|
||||
layout(set = 2, binding = 0) uniform textureCube radiance;
|
||||
#ifdef USE_CUBEMAP_PASS
|
||||
layout(set = 2, binding = 1) uniform textureCube half_res;
|
||||
layout(set = 2, binding = 2) uniform textureCube quarter_res;
|
||||
#else
|
||||
layout(set = 2, binding = 1) uniform texture2D half_res;
|
||||
layout(set = 2, binding = 2) uniform texture2D quarter_res;
|
||||
#endif
|
||||
|
||||
#ifdef USE_CUBEMAP_PASS
|
||||
#define AT_CUBEMAP_PASS true
|
||||
#else
|
||||
#define AT_CUBEMAP_PASS false
|
||||
#endif
|
||||
|
||||
#ifdef USE_HALF_RES_PASS
|
||||
#define AT_HALF_RES_PASS true
|
||||
#else
|
||||
#define AT_HALF_RES_PASS false
|
||||
#endif
|
||||
|
||||
#ifdef USE_QUARTER_RES_PASS
|
||||
#define AT_QUARTER_RES_PASS true
|
||||
#else
|
||||
#define AT_QUARTER_RES_PASS false
|
||||
#endif
|
||||
|
||||
struct DirectionalLightData {
|
||||
vec3 direction;
|
||||
float energy;
|
||||
vec3 color;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
layout(set = 3, binding = 0, std140) uniform DirectionalLights {
|
||||
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
|
||||
}
|
||||
directional_lights;
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
FRAGMENT_SHADER_GLOBALS
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
void main() {
|
||||
|
||||
vec3 cube_normal;
|
||||
cube_normal.z = -1.0;
|
||||
cube_normal.x = (cube_normal.z * (-uv_interp.x - params.proj.x)) / params.proj.y;
|
||||
cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.proj.z)) / params.proj.w;
|
||||
cube_normal = mat3(params.orientation) * cube_normal;
|
||||
cube_normal.z = -cube_normal.z;
|
||||
cube_normal = normalize(cube_normal);
|
||||
|
||||
vec2 uv = uv_interp * 0.5 + 0.5;
|
||||
|
||||
vec2 panorama_coords = vec2(atan(cube_normal.x, cube_normal.z), acos(cube_normal.y));
|
||||
|
||||
if (panorama_coords.x < 0.0) {
|
||||
panorama_coords.x += M_PI * 2.0;
|
||||
}
|
||||
|
||||
panorama_coords /= vec2(M_PI * 2.0, M_PI);
|
||||
|
||||
vec3 color = vec3(0.0, 0.0, 0.0);
|
||||
float alpha = 1.0; // Only available to subpasses
|
||||
vec4 half_res_color = vec4(1.0);
|
||||
vec4 quarter_res_color = vec4(1.0);
|
||||
|
||||
#ifdef USE_CUBEMAP_PASS
|
||||
float using_cubemap = 1.0;
|
||||
#ifdef USES_HALF_RES_COLOR
|
||||
half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal);
|
||||
#endif
|
||||
#ifdef USES_QUARTER_RES_COLOR
|
||||
quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal);
|
||||
#endif
|
||||
#else
|
||||
float using_cubemap = 0.0;
|
||||
#ifdef USES_HALF_RES_COLOR
|
||||
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);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// unused, just here to make our compiler happy, make sure we don't execute any light code the user adds in..
|
||||
#ifndef REALLYINCLUDETHIS
|
||||
{
|
||||
/* clang-format off */
|
||||
|
||||
LIGHT_SHADER_CODE
|
||||
|
||||
/* clang-format on */
|
||||
}
|
||||
#endif
|
||||
{
|
||||
/* clang-format off */
|
||||
|
||||
FRAGMENT_SHADER_CODE
|
||||
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
frag_color.rgb = color * params.position_multiplier.w;
|
||||
frag_color.a = alpha;
|
||||
}
|
||||
252
servers/rendering/rasterizer_rd/shaders/ssao.glsl
Normal file
252
servers/rendering/rasterizer_rd/shaders/ssao.glsl
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
/* clang-format off */
|
||||
[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
/* clang-format on */
|
||||
|
||||
#define TWO_PI 6.283185307179586476925286766559
|
||||
|
||||
#ifdef SSAO_QUALITY_HIGH
|
||||
#define NUM_SAMPLES (20)
|
||||
#endif
|
||||
|
||||
#ifdef SSAO_QUALITY_ULTRA
|
||||
#define NUM_SAMPLES (48)
|
||||
#endif
|
||||
|
||||
#ifdef SSAO_QUALITY_LOW
|
||||
#define NUM_SAMPLES (8)
|
||||
#endif
|
||||
|
||||
#if !defined(SSAO_QUALITY_LOW) && !defined(SSAO_QUALITY_HIGH) && !defined(SSAO_QUALITY_ULTRA)
|
||||
#define NUM_SAMPLES (12)
|
||||
#endif
|
||||
|
||||
// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower
|
||||
// miplevel to maintain reasonable spatial locality in the cache
|
||||
// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing.
|
||||
// If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively
|
||||
#define LOG_MAX_OFFSET (3)
|
||||
|
||||
// This must be less than or equal to the MAX_MIP_LEVEL defined in SSAO.cpp
|
||||
#define MAX_MIP_LEVEL (4)
|
||||
|
||||
// This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent
|
||||
// taps from lining up. This particular choice was tuned for NUM_SAMPLES == 9
|
||||
|
||||
const int ROTATIONS[] = int[](
|
||||
1, 1, 2, 3, 2, 5, 2, 3, 2,
|
||||
3, 3, 5, 5, 3, 4, 7, 5, 5, 7,
|
||||
9, 8, 5, 5, 7, 7, 7, 8, 5, 8,
|
||||
11, 12, 7, 10, 13, 8, 11, 8, 7, 14,
|
||||
11, 11, 13, 12, 13, 19, 17, 13, 11, 18,
|
||||
19, 11, 11, 14, 17, 21, 15, 16, 17, 18,
|
||||
13, 17, 11, 17, 19, 18, 25, 18, 19, 19,
|
||||
29, 21, 19, 27, 31, 29, 21, 18, 17, 29,
|
||||
31, 31, 23, 18, 25, 26, 25, 23, 19, 34,
|
||||
19, 27, 21, 25, 39, 29, 17, 21, 27);
|
||||
/* clang-format on */
|
||||
|
||||
//#define NUM_SPIRAL_TURNS (7)
|
||||
const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES - 1];
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_depth_mipmaps;
|
||||
layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_image;
|
||||
|
||||
#ifndef USE_HALF_SIZE
|
||||
layout(set = 2, binding = 0) uniform sampler2D source_depth;
|
||||
#endif
|
||||
|
||||
layout(set = 3, binding = 0) uniform sampler2D source_normal;
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
ivec2 screen_size;
|
||||
float z_far;
|
||||
float z_near;
|
||||
|
||||
bool orthogonal;
|
||||
float intensity_div_r6;
|
||||
float radius;
|
||||
float bias;
|
||||
|
||||
vec4 proj_info;
|
||||
vec2 pixel_size;
|
||||
float proj_scale;
|
||||
uint pad;
|
||||
}
|
||||
params;
|
||||
|
||||
vec3 reconstructCSPosition(vec2 S, float z) {
|
||||
if (params.orthogonal) {
|
||||
return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z);
|
||||
} else {
|
||||
return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z);
|
||||
}
|
||||
}
|
||||
|
||||
vec3 getPosition(ivec2 ssP) {
|
||||
vec3 P;
|
||||
#ifdef USE_HALF_SIZE
|
||||
P.z = texelFetch(source_depth_mipmaps, ssP, 0).r;
|
||||
P.z = -P.z;
|
||||
#else
|
||||
P.z = texelFetch(source_depth, ssP, 0).r;
|
||||
|
||||
P.z = P.z * 2.0 - 1.0;
|
||||
if (params.orthogonal) {
|
||||
P.z = ((P.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
|
||||
} else {
|
||||
P.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - P.z * (params.z_far - params.z_near));
|
||||
}
|
||||
P.z = -P.z;
|
||||
#endif
|
||||
// Offset to pixel center
|
||||
P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z);
|
||||
return P;
|
||||
}
|
||||
|
||||
/** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */
|
||||
vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR) {
|
||||
// Radius relative to ssR
|
||||
float alpha = (float(sampleNumber) + 0.5) * (1.0 / float(NUM_SAMPLES));
|
||||
float angle = alpha * (float(NUM_SPIRAL_TURNS) * 6.28) + spinAngle;
|
||||
|
||||
ssR = alpha;
|
||||
return vec2(cos(angle), sin(angle));
|
||||
}
|
||||
|
||||
/** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR. Assumes length(unitOffset) == 1 */
|
||||
vec3 getOffsetPosition(ivec2 ssP, float ssR) {
|
||||
// Derivation:
|
||||
// mipLevel = floor(log(ssR / MAX_OFFSET));
|
||||
|
||||
int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL);
|
||||
|
||||
vec3 P;
|
||||
|
||||
// We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map.
|
||||
// Manually clamp to the texture size because texelFetch bypasses the texture unit
|
||||
ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), (params.screen_size >> mipLevel) - ivec2(1));
|
||||
|
||||
#ifdef USE_HALF_SIZE
|
||||
P.z = texelFetch(source_depth_mipmaps, mipP, mipLevel).r;
|
||||
P.z = -P.z;
|
||||
#else
|
||||
if (mipLevel < 1) {
|
||||
//read from depth buffer
|
||||
P.z = texelFetch(source_depth, mipP, 0).r;
|
||||
P.z = P.z * 2.0 - 1.0;
|
||||
if (params.orthogonal) {
|
||||
P.z = ((P.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
|
||||
} else {
|
||||
P.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - P.z * (params.z_far - params.z_near));
|
||||
}
|
||||
P.z = -P.z;
|
||||
|
||||
} else {
|
||||
//read from mipmaps
|
||||
P.z = texelFetch(source_depth_mipmaps, mipP, mipLevel - 1).r;
|
||||
P.z = -P.z;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Offset to pixel center
|
||||
P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z);
|
||||
|
||||
return P;
|
||||
}
|
||||
|
||||
/** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds
|
||||
to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius
|
||||
|
||||
Note that units of H() in the HPG12 paper are meters, not
|
||||
unitless. The whole falloff/sampling function is therefore
|
||||
unitless. In this implementation, we factor out (9 / radius).
|
||||
|
||||
Four versions of the falloff function are implemented below
|
||||
*/
|
||||
float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in float p_radius, in int tapIndex, in float randomPatternRotationAngle) {
|
||||
// Offset on the unit disk, spun for this pixel
|
||||
float ssR;
|
||||
vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR);
|
||||
ssR *= ssDiskRadius;
|
||||
|
||||
ivec2 ssP = ivec2(ssR * unitOffset) + ssC;
|
||||
|
||||
if (any(lessThan(ssP, ivec2(0))) || any(greaterThanEqual(ssP, params.screen_size))) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// The occluding point in camera space
|
||||
vec3 Q = getOffsetPosition(ssP, ssR);
|
||||
|
||||
vec3 v = Q - C;
|
||||
|
||||
float vv = dot(v, v);
|
||||
float vn = dot(v, n_C);
|
||||
|
||||
const float epsilon = 0.01;
|
||||
float radius2 = p_radius * p_radius;
|
||||
|
||||
// A: From the HPG12 paper
|
||||
// Note large epsilon to avoid overdarkening within cracks
|
||||
//return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6;
|
||||
|
||||
// B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended]
|
||||
float f = max(radius2 - vv, 0.0);
|
||||
return f * f * f * max((vn - params.bias) / (epsilon + vv), 0.0);
|
||||
|
||||
// C: Medium contrast (which looks better at high radii), no division. Note that the
|
||||
// contribution still falls off with radius^2, but we've adjusted the rate in a way that is
|
||||
// more computationally efficient and happens to be aesthetically pleasing.
|
||||
// return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0);
|
||||
|
||||
// D: Low contrast, no division operation
|
||||
// return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Pixel being shaded
|
||||
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
|
||||
if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
// World space point being shaded
|
||||
vec3 C = getPosition(ssC);
|
||||
|
||||
#ifdef USE_HALF_SIZE
|
||||
vec3 n_C = texelFetch(source_normal, ssC << 1, 0).xyz * 2.0 - 1.0;
|
||||
#else
|
||||
vec3 n_C = texelFetch(source_normal, ssC, 0).xyz * 2.0 - 1.0;
|
||||
#endif
|
||||
n_C = normalize(n_C);
|
||||
n_C.y = -n_C.y; //because this code reads flipped
|
||||
|
||||
// Hash function used in the HPG12 AlchemyAO paper
|
||||
float randomPatternRotationAngle = mod(float((3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10), TWO_PI);
|
||||
|
||||
// Reconstruct normals from positions. These will lead to 1-pixel black lines
|
||||
// at depth discontinuities, however the blur will wipe those out so they are not visible
|
||||
// in the final image.
|
||||
|
||||
// Choose the screen-space sample radius
|
||||
// proportional to the projected area of the sphere
|
||||
|
||||
float ssDiskRadius = -params.proj_scale * params.radius;
|
||||
if (!params.orthogonal) {
|
||||
ssDiskRadius = -params.proj_scale * params.radius / C.z;
|
||||
}
|
||||
float sum = 0.0;
|
||||
for (int i = 0; i < NUM_SAMPLES; ++i) {
|
||||
sum += sampleAO(ssC, C, n_C, ssDiskRadius, params.radius, i, randomPatternRotationAngle);
|
||||
}
|
||||
|
||||
float A = max(0.0, 1.0 - sum * params.intensity_div_r6 * (5.0 / float(NUM_SAMPLES)));
|
||||
|
||||
imageStore(dest_image, ssC, vec4(A));
|
||||
}
|
||||
157
servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl
Normal file
157
servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/* clang-format off */
|
||||
[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
/* clang-format on */
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_ssao;
|
||||
layout(set = 1, binding = 0) uniform sampler2D source_depth;
|
||||
#ifdef MODE_UPSCALE
|
||||
layout(set = 2, binding = 0) uniform sampler2D source_depth_mipmaps;
|
||||
#endif
|
||||
|
||||
layout(r8, set = 3, binding = 0) uniform restrict writeonly image2D dest_image;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tunable Parameters:
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
float edge_sharpness; /** Increase to make depth edges crisper. Decrease to reduce flicker. */
|
||||
int filter_scale;
|
||||
float z_far;
|
||||
float z_near;
|
||||
bool orthogonal;
|
||||
uint pad0;
|
||||
uint pad1;
|
||||
uint pad2;
|
||||
ivec2 axis; /** (1, 0) or (0, 1) */
|
||||
ivec2 screen_size;
|
||||
}
|
||||
params;
|
||||
|
||||
/** Filter radius in pixels. This will be multiplied by SCALE. */
|
||||
#define R (4)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Gaussian coefficients
|
||||
const float gaussian[R + 1] =
|
||||
//float[](0.356642, 0.239400, 0.072410, 0.009869);
|
||||
//float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0
|
||||
float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0
|
||||
//float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0
|
||||
|
||||
void main() {
|
||||
|
||||
// Pixel being shaded
|
||||
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
|
||||
if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MODE_UPSCALE
|
||||
|
||||
//closest one should be the same pixel, but check nearby just in case
|
||||
float depth = texelFetch(source_depth, ssC, 0).r;
|
||||
|
||||
depth = depth * 2.0 - 1.0;
|
||||
if (params.orthogonal) {
|
||||
depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
|
||||
} else {
|
||||
depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
|
||||
}
|
||||
|
||||
vec2 pixel_size = 1.0 / vec2(params.screen_size);
|
||||
vec2 closest_uv = vec2(ssC) * pixel_size + pixel_size * 0.5;
|
||||
vec2 from_uv = closest_uv;
|
||||
vec2 ps2 = pixel_size; // * 2.0;
|
||||
|
||||
float closest_depth = abs(textureLod(source_depth_mipmaps, closest_uv, 0.0).r - depth);
|
||||
|
||||
vec2 offsets[4] = vec2[](vec2(ps2.x, 0), vec2(-ps2.x, 0), vec2(0, ps2.y), vec2(0, -ps2.y));
|
||||
for (int i = 0; i < 4; i++) {
|
||||
vec2 neighbour = from_uv + offsets[i];
|
||||
float neighbour_depth = abs(textureLod(source_depth_mipmaps, neighbour, 0.0).r - depth);
|
||||
if (neighbour_depth < closest_depth) {
|
||||
closest_uv = neighbour;
|
||||
closest_depth = neighbour_depth;
|
||||
}
|
||||
}
|
||||
|
||||
float visibility = textureLod(source_ssao, closest_uv, 0.0).r;
|
||||
imageStore(dest_image, ssC, vec4(visibility));
|
||||
#else
|
||||
|
||||
float depth = texelFetch(source_depth, ssC, 0).r;
|
||||
|
||||
#ifdef MODE_FULL_SIZE
|
||||
depth = depth * 2.0 - 1.0;
|
||||
|
||||
if (params.orthogonal) {
|
||||
depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
|
||||
} else {
|
||||
depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
|
||||
}
|
||||
|
||||
#endif
|
||||
float depth_divide = 1.0 / params.z_far;
|
||||
|
||||
//depth *= depth_divide;
|
||||
|
||||
/*
|
||||
if (depth > params.z_far * 0.999) {
|
||||
discard; //skybox
|
||||
}
|
||||
*/
|
||||
|
||||
float sum = texelFetch(source_ssao, ssC, 0).r;
|
||||
|
||||
// Base weight for depth falloff. Increase this for more blurriness,
|
||||
// decrease it for better edge discrimination
|
||||
float BASE = gaussian[0];
|
||||
float totalWeight = BASE;
|
||||
sum *= totalWeight;
|
||||
|
||||
ivec2 clamp_limit = params.screen_size - ivec2(1);
|
||||
|
||||
for (int r = -R; r <= R; ++r) {
|
||||
// We already handled the zero case above. This loop should be unrolled and the static branch optimized out,
|
||||
// so the IF statement has no runtime cost
|
||||
if (r != 0) {
|
||||
|
||||
ivec2 ppos = ssC + params.axis * (r * params.filter_scale);
|
||||
float value = texelFetch(source_ssao, clamp(ppos, ivec2(0), clamp_limit), 0).r;
|
||||
ivec2 rpos = clamp(ppos, ivec2(0), clamp_limit);
|
||||
|
||||
float temp_depth = texelFetch(source_depth, rpos, 0).r;
|
||||
#ifdef MODE_FULL_SIZE
|
||||
temp_depth = temp_depth * 2.0 - 1.0;
|
||||
if (params.orthogonal) {
|
||||
temp_depth = ((temp_depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
|
||||
} else {
|
||||
temp_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - temp_depth * (params.z_far - params.z_near));
|
||||
}
|
||||
//temp_depth *= depth_divide;
|
||||
#endif
|
||||
// spatial domain: offset gaussian tap
|
||||
float weight = 0.3 + gaussian[abs(r)];
|
||||
//weight *= max(0.0, dot(temp_normal, normal));
|
||||
|
||||
// range domain (the "bilateral" weight). As depth difference increases, decrease weight.
|
||||
weight *= max(0.0, 1.0 - params.edge_sharpness * abs(temp_depth - depth));
|
||||
|
||||
sum += value * weight;
|
||||
totalWeight += weight;
|
||||
}
|
||||
}
|
||||
|
||||
const float epsilon = 0.0001;
|
||||
float visibility = sum / (totalWeight + epsilon);
|
||||
|
||||
imageStore(dest_image, ssC, vec4(visibility));
|
||||
#endif
|
||||
}
|
||||
48
servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl
Normal file
48
servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/* clang-format off */
|
||||
[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
/* clang-format on */
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
vec2 pixel_size;
|
||||
float z_far;
|
||||
float z_near;
|
||||
ivec2 source_size;
|
||||
bool orthogonal;
|
||||
uint pad;
|
||||
}
|
||||
params;
|
||||
|
||||
#ifdef MINIFY_START
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_texture;
|
||||
#else
|
||||
layout(r32f, set = 0, binding = 0) uniform restrict readonly image2D source_image;
|
||||
#endif
|
||||
layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_image;
|
||||
|
||||
void main() {
|
||||
|
||||
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
if (any(greaterThan(pos, params.source_size >> 1))) { //too large, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MINIFY_START
|
||||
float depth = texelFetch(source_texture, pos << 1, 0).r * 2.0 - 1.0;
|
||||
if (params.orthogonal) {
|
||||
depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
|
||||
} else {
|
||||
depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near));
|
||||
}
|
||||
#else
|
||||
float depth = imageLoad(source_image, pos << 1).r;
|
||||
#endif
|
||||
|
||||
imageStore(dest_image, pos, vec4(depth));
|
||||
}
|
||||
305
servers/rendering/rasterizer_rd/shaders/tonemap.glsl
Normal file
305
servers/rendering/rasterizer_rd/shaders/tonemap.glsl
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
/* clang-format off */
|
||||
[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(location = 0) out vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
void main() {
|
||||
|
||||
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
||||
uv_interp = base_arr[gl_VertexIndex];
|
||||
gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
[fragment]
|
||||
|
||||
#version 450
|
||||
|
||||
VERSION_DEFINES
|
||||
|
||||
layout(location = 0) in vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D source_color;
|
||||
layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure;
|
||||
layout(set = 2, binding = 0) uniform sampler2D source_glow;
|
||||
layout(set = 3, binding = 0) uniform sampler3D color_correction;
|
||||
|
||||
layout(push_constant, binding = 1, std430) uniform Params {
|
||||
vec3 bcs;
|
||||
bool use_bcs;
|
||||
|
||||
bool use_glow;
|
||||
bool use_auto_exposure;
|
||||
bool use_color_correction;
|
||||
uint tonemapper;
|
||||
|
||||
uvec2 glow_texture_size;
|
||||
|
||||
float glow_intensity;
|
||||
uint glow_level_flags;
|
||||
uint glow_mode;
|
||||
|
||||
float exposure;
|
||||
float white;
|
||||
float auto_exposure_grey;
|
||||
}
|
||||
params;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
#ifdef USE_GLOW_FILTER_BICUBIC
|
||||
// w0, w1, w2, and w3 are the four cubic B-spline basis functions
|
||||
float w0(float a) {
|
||||
return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f);
|
||||
}
|
||||
|
||||
float w1(float a) {
|
||||
return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f);
|
||||
}
|
||||
|
||||
float w2(float a) {
|
||||
return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f);
|
||||
}
|
||||
|
||||
float w3(float a) {
|
||||
return (1.0f / 6.0f) * (a * a * a);
|
||||
}
|
||||
|
||||
// g0 and g1 are the two amplitude functions
|
||||
float g0(float a) {
|
||||
return w0(a) + w1(a);
|
||||
}
|
||||
|
||||
float g1(float a) {
|
||||
return w2(a) + w3(a);
|
||||
}
|
||||
|
||||
// h0 and h1 are the two offset functions
|
||||
float h0(float a) {
|
||||
return -1.0f + w1(a) / (w0(a) + w1(a));
|
||||
}
|
||||
|
||||
float h1(float a) {
|
||||
return 1.0f + w3(a) / (w2(a) + w3(a));
|
||||
}
|
||||
|
||||
vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) {
|
||||
float lod = float(p_lod);
|
||||
vec2 tex_size = vec2(params.glow_texture_size >> p_lod);
|
||||
vec2 pixel_size = vec2(1.0f) / tex_size;
|
||||
|
||||
uv = uv * tex_size + vec2(0.5f);
|
||||
|
||||
vec2 iuv = floor(uv);
|
||||
vec2 fuv = fract(uv);
|
||||
|
||||
float g0x = g0(fuv.x);
|
||||
float g1x = g1(fuv.x);
|
||||
float h0x = h0(fuv.x);
|
||||
float h1x = h1(fuv.x);
|
||||
float h0y = h0(fuv.y);
|
||||
float h1y = h1(fuv.y);
|
||||
|
||||
vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - vec2(0.5f)) * pixel_size;
|
||||
vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5f)) * pixel_size;
|
||||
vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5f)) * pixel_size;
|
||||
vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5f)) * pixel_size;
|
||||
|
||||
return (g0(fuv.y) * (g0x * textureLod(tex, p0, lod) + g1x * textureLod(tex, p1, lod))) +
|
||||
(g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod)));
|
||||
}
|
||||
|
||||
#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod)
|
||||
|
||||
#else
|
||||
|
||||
#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, m_uv, float(m_lod))
|
||||
|
||||
#endif
|
||||
|
||||
vec3 tonemap_filmic(vec3 color, float 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 white_tonemapped = ((white * (A * white + C * B) + D * E) / (white * (A * white + B) + D * F)) - E / F;
|
||||
|
||||
return color_tonemapped / white_tonemapped;
|
||||
}
|
||||
|
||||
vec3 tonemap_aces(vec3 color, float white) {
|
||||
const float exposure_bias = 0.85f;
|
||||
const float A = 2.51f * exposure_bias * exposure_bias;
|
||||
const float B = 0.03f * exposure_bias;
|
||||
const float C = 2.43f * exposure_bias * exposure_bias;
|
||||
const float D = 0.59f * exposure_bias;
|
||||
const float E = 0.14f;
|
||||
|
||||
vec3 color_tonemapped = (color * (A * color + B)) / (color * (C * color + D) + E);
|
||||
float white_tonemapped = (white * (A * white + B)) / (white * (C * white + D) + E);
|
||||
|
||||
return color_tonemapped / white_tonemapped;
|
||||
}
|
||||
|
||||
vec3 tonemap_reinhard(vec3 color, float white) {
|
||||
return (white * color + color) / (color * white + 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 white) { // inputs are LINEAR, always outputs clamped [0;1] color
|
||||
|
||||
if (params.tonemapper == TONEMAPPER_LINEAR) {
|
||||
return color;
|
||||
} else if (params.tonemapper == TONEMAPPER_REINHARD) {
|
||||
return tonemap_reinhard(color, white);
|
||||
} else if (params.tonemapper == TONEMAPPER_FILMIC) {
|
||||
return tonemap_filmic(color, white);
|
||||
} else { //aces
|
||||
return tonemap_aces(color, white);
|
||||
}
|
||||
}
|
||||
|
||||
vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels
|
||||
vec3 glow = vec3(0.0f);
|
||||
|
||||
if (bool(params.glow_level_flags & (1 << 0))) {
|
||||
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 0).rgb;
|
||||
}
|
||||
|
||||
if (bool(params.glow_level_flags & (1 << 1))) {
|
||||
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 1).rgb;
|
||||
}
|
||||
|
||||
if (bool(params.glow_level_flags & (1 << 2))) {
|
||||
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 2).rgb;
|
||||
}
|
||||
|
||||
if (bool(params.glow_level_flags & (1 << 3))) {
|
||||
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 3).rgb;
|
||||
}
|
||||
|
||||
if (bool(params.glow_level_flags & (1 << 4))) {
|
||||
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 4).rgb;
|
||||
}
|
||||
|
||||
if (bool(params.glow_level_flags & (1 << 5))) {
|
||||
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 5).rgb;
|
||||
}
|
||||
|
||||
if (bool(params.glow_level_flags & (1 << 6))) {
|
||||
glow += GLOW_TEXTURE_SAMPLE(tex, uv, 6).rgb;
|
||||
}
|
||||
|
||||
return glow;
|
||||
}
|
||||
|
||||
#define GLOW_MODE_ADD 0
|
||||
#define GLOW_MODE_SCREEN 1
|
||||
#define GLOW_MODE_SOFTLIGHT 2
|
||||
#define GLOW_MODE_REPLACE 3
|
||||
#define GLOW_MODE_MIX 4
|
||||
|
||||
vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blending mode
|
||||
if (params.glow_mode == GLOW_MODE_ADD) {
|
||||
return color + glow;
|
||||
} else if (params.glow_mode == GLOW_MODE_SCREEN) {
|
||||
//need color clamping
|
||||
return max((color + glow) - (color * glow), vec3(0.0));
|
||||
} else if (params.glow_mode == GLOW_MODE_SOFTLIGHT) {
|
||||
//need color clamping
|
||||
glow = glow * vec3(0.5f) + vec3(0.5f);
|
||||
|
||||
color.r = (glow.r <= 0.5f) ? (color.r - (1.0f - 2.0f * glow.r) * color.r * (1.0f - color.r)) : (((glow.r > 0.5f) && (color.r <= 0.25f)) ? (color.r + (2.0f * glow.r - 1.0f) * (4.0f * color.r * (4.0f * color.r + 1.0f) * (color.r - 1.0f) + 7.0f * color.r)) : (color.r + (2.0f * glow.r - 1.0f) * (sqrt(color.r) - color.r)));
|
||||
color.g = (glow.g <= 0.5f) ? (color.g - (1.0f - 2.0f * glow.g) * color.g * (1.0f - color.g)) : (((glow.g > 0.5f) && (color.g <= 0.25f)) ? (color.g + (2.0f * glow.g - 1.0f) * (4.0f * color.g * (4.0f * color.g + 1.0f) * (color.g - 1.0f) + 7.0f * color.g)) : (color.g + (2.0f * glow.g - 1.0f) * (sqrt(color.g) - color.g)));
|
||||
color.b = (glow.b <= 0.5f) ? (color.b - (1.0f - 2.0f * glow.b) * color.b * (1.0f - color.b)) : (((glow.b > 0.5f) && (color.b <= 0.25f)) ? (color.b + (2.0f * glow.b - 1.0f) * (4.0f * color.b * (4.0f * color.b + 1.0f) * (color.b - 1.0f) + 7.0f * color.b)) : (color.b + (2.0f * glow.b - 1.0f) * (sqrt(color.b) - color.b)));
|
||||
return color;
|
||||
} else { //replace
|
||||
return glow;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 apply_bcs(vec3 color, vec3 bcs) {
|
||||
color = mix(vec3(0.0f), color, bcs.x);
|
||||
color = mix(vec3(0.5f), color, bcs.y);
|
||||
color = mix(vec3(dot(vec3(1.0f), color) * 0.33333f), color, bcs.z);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
vec3 apply_color_correction(vec3 color, sampler3D correction_tex) {
|
||||
return texture(correction_tex, color).rgb;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb;
|
||||
|
||||
// Exposure
|
||||
|
||||
if (params.use_auto_exposure) {
|
||||
color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.auto_exposure_grey;
|
||||
}
|
||||
|
||||
color *= params.exposure;
|
||||
|
||||
// Early Tonemap & SRGB Conversion
|
||||
|
||||
if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) {
|
||||
|
||||
vec3 glow = gather_glow(source_glow, uv_interp);
|
||||
color.rgb = mix(color.rgb, glow, params.glow_intensity);
|
||||
}
|
||||
|
||||
color = apply_tonemapping(color, params.white);
|
||||
|
||||
color = linear_to_srgb(color); // regular linear -> SRGB conversion
|
||||
|
||||
// Glow
|
||||
|
||||
if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) {
|
||||
|
||||
vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity;
|
||||
|
||||
// high dynamic range -> SRGB
|
||||
glow = apply_tonemapping(glow, params.white);
|
||||
glow = linear_to_srgb(glow);
|
||||
|
||||
color = apply_glow(color, glow);
|
||||
}
|
||||
|
||||
// Additional effects
|
||||
|
||||
if (params.use_bcs) {
|
||||
color = apply_bcs(color, params.bcs);
|
||||
}
|
||||
|
||||
if (params.use_color_correction) {
|
||||
color = apply_color_correction(color, color_correction);
|
||||
}
|
||||
|
||||
frag_color = vec4(color, 1.0f);
|
||||
}
|
||||
64
servers/rendering/rendering_device.cpp
Normal file
64
servers/rendering/rendering_device.cpp
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*************************************************************************/
|
||||
/* rendering_device.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "rendering_device.h"
|
||||
|
||||
RenderingDevice *RenderingDevice::singleton = NULL;
|
||||
|
||||
RenderingDevice *RenderingDevice::get_singleton() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
RenderingDevice::ShaderCompileFunction RenderingDevice::compile_function = NULL;
|
||||
RenderingDevice::ShaderCacheFunction RenderingDevice::cache_function = NULL;
|
||||
|
||||
void RenderingDevice::shader_set_compile_function(ShaderCompileFunction p_function) {
|
||||
compile_function = p_function;
|
||||
}
|
||||
void RenderingDevice::shader_set_cache_function(ShaderCacheFunction p_function) {
|
||||
cache_function = p_function;
|
||||
}
|
||||
|
||||
Vector<uint8_t> RenderingDevice::shader_compile_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, bool p_allow_cache) {
|
||||
if (p_allow_cache && cache_function) {
|
||||
Vector<uint8_t> cache = cache_function(p_stage, p_source_code, p_language);
|
||||
if (cache.size()) {
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V(!compile_function, Vector<uint8_t>());
|
||||
|
||||
return compile_function(p_stage, p_source_code, p_language, r_error);
|
||||
}
|
||||
|
||||
RenderingDevice::RenderingDevice() {
|
||||
singleton = this;
|
||||
}
|
||||
1032
servers/rendering/rendering_device.h
Normal file
1032
servers/rendering/rendering_device.h
Normal file
File diff suppressed because it is too large
Load diff
1479
servers/rendering/rendering_server_canvas.cpp
Normal file
1479
servers/rendering/rendering_server_canvas.cpp
Normal file
File diff suppressed because it is too large
Load diff
270
servers/rendering/rendering_server_canvas.h
Normal file
270
servers/rendering/rendering_server_canvas.h
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
/*************************************************************************/
|
||||
/* rendering_server_canvas.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef VISUALSERVERCANVAS_H
|
||||
#define VISUALSERVERCANVAS_H
|
||||
|
||||
#include "rasterizer.h"
|
||||
#include "rendering_server_viewport.h"
|
||||
|
||||
class RenderingServerCanvas {
|
||||
public:
|
||||
struct Item : public RasterizerCanvas::Item {
|
||||
|
||||
RID parent; // canvas it belongs to
|
||||
List<Item *>::Element *E;
|
||||
int z_index;
|
||||
bool z_relative;
|
||||
bool sort_y;
|
||||
Color modulate;
|
||||
Color self_modulate;
|
||||
bool use_parent_material;
|
||||
int index;
|
||||
bool children_order_dirty;
|
||||
int ysort_children_count;
|
||||
Color ysort_modulate;
|
||||
Transform2D ysort_xform;
|
||||
Vector2 ysort_pos;
|
||||
RS::CanvasItemTextureFilter texture_filter;
|
||||
RS::CanvasItemTextureRepeat texture_repeat;
|
||||
|
||||
Vector<Item *> child_items;
|
||||
|
||||
Item() {
|
||||
children_order_dirty = true;
|
||||
E = NULL;
|
||||
z_index = 0;
|
||||
modulate = Color(1, 1, 1, 1);
|
||||
self_modulate = Color(1, 1, 1, 1);
|
||||
sort_y = false;
|
||||
use_parent_material = false;
|
||||
z_relative = true;
|
||||
index = 0;
|
||||
ysort_children_count = -1;
|
||||
ysort_xform = Transform2D();
|
||||
ysort_pos = Vector2();
|
||||
texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
|
||||
texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
|
||||
}
|
||||
};
|
||||
|
||||
struct ItemIndexSort {
|
||||
|
||||
_FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const {
|
||||
|
||||
return p_left->index < p_right->index;
|
||||
}
|
||||
};
|
||||
|
||||
struct ItemPtrSort {
|
||||
|
||||
_FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const {
|
||||
|
||||
if (Math::is_equal_approx(p_left->ysort_pos.y, p_right->ysort_pos.y))
|
||||
return p_left->ysort_pos.x < p_right->ysort_pos.x;
|
||||
|
||||
return p_left->ysort_pos.y < p_right->ysort_pos.y;
|
||||
}
|
||||
};
|
||||
|
||||
struct LightOccluderPolygon {
|
||||
|
||||
bool active;
|
||||
Rect2 aabb;
|
||||
RS::CanvasOccluderPolygonCullMode cull_mode;
|
||||
RID occluder;
|
||||
Set<RasterizerCanvas::LightOccluderInstance *> owners;
|
||||
|
||||
LightOccluderPolygon() {
|
||||
active = false;
|
||||
cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED;
|
||||
}
|
||||
};
|
||||
|
||||
RID_PtrOwner<LightOccluderPolygon> canvas_light_occluder_polygon_owner;
|
||||
|
||||
RID_PtrOwner<RasterizerCanvas::LightOccluderInstance> canvas_light_occluder_owner;
|
||||
|
||||
struct Canvas : public RenderingServerViewport::CanvasBase {
|
||||
|
||||
Set<RID> viewports;
|
||||
struct ChildItem {
|
||||
|
||||
Point2 mirror;
|
||||
Item *item;
|
||||
bool operator<(const ChildItem &p_item) const {
|
||||
return item->index < p_item.item->index;
|
||||
}
|
||||
};
|
||||
|
||||
Set<RasterizerCanvas::Light *> lights;
|
||||
|
||||
Set<RasterizerCanvas::LightOccluderInstance *> occluders;
|
||||
|
||||
bool children_order_dirty;
|
||||
Vector<ChildItem> child_items;
|
||||
Color modulate;
|
||||
RID parent;
|
||||
float parent_scale;
|
||||
|
||||
int find_item(Item *p_item) {
|
||||
for (int i = 0; i < child_items.size(); i++) {
|
||||
if (child_items[i].item == p_item)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
void erase_item(Item *p_item) {
|
||||
int idx = find_item(p_item);
|
||||
if (idx >= 0)
|
||||
child_items.remove(idx);
|
||||
}
|
||||
|
||||
Canvas() {
|
||||
modulate = Color(1, 1, 1, 1);
|
||||
children_order_dirty = true;
|
||||
parent_scale = 1.0;
|
||||
}
|
||||
};
|
||||
|
||||
mutable RID_PtrOwner<Canvas> canvas_owner;
|
||||
RID_PtrOwner<Item> canvas_item_owner;
|
||||
RID_PtrOwner<RasterizerCanvas::Light> canvas_light_owner;
|
||||
|
||||
bool disable_scale;
|
||||
|
||||
private:
|
||||
void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights);
|
||||
void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner);
|
||||
void _light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights);
|
||||
|
||||
RasterizerCanvas::Item **z_list;
|
||||
RasterizerCanvas::Item **z_last_list;
|
||||
|
||||
public:
|
||||
void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect);
|
||||
|
||||
RID canvas_create();
|
||||
void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring);
|
||||
void canvas_set_modulate(RID p_canvas, const Color &p_color);
|
||||
void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale);
|
||||
void canvas_set_disable_scale(bool p_disable);
|
||||
|
||||
RID canvas_item_create();
|
||||
void canvas_item_set_parent(RID p_item, RID p_parent);
|
||||
|
||||
void canvas_item_set_visible(RID p_item, bool p_visible);
|
||||
void canvas_item_set_light_mask(RID p_item, int p_mask);
|
||||
|
||||
void canvas_item_set_transform(RID p_item, const Transform2D &p_transform);
|
||||
void canvas_item_set_clip(RID p_item, bool p_clip);
|
||||
void canvas_item_set_distance_field_mode(RID p_item, bool p_enable);
|
||||
void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect = Rect2());
|
||||
void canvas_item_set_modulate(RID p_item, const Color &p_color);
|
||||
void canvas_item_set_self_modulate(RID p_item, const Color &p_color);
|
||||
|
||||
void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable);
|
||||
|
||||
void canvas_item_set_update_when_visible(RID p_item, bool p_update);
|
||||
|
||||
void canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter);
|
||||
void canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat);
|
||||
|
||||
void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0);
|
||||
void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0);
|
||||
void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0);
|
||||
void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color);
|
||||
void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color);
|
||||
void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT);
|
||||
void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), bool p_clip_uv = false, RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT);
|
||||
void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT);
|
||||
void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT);
|
||||
void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT);
|
||||
void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT);
|
||||
void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT);
|
||||
void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT);
|
||||
void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT);
|
||||
void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform);
|
||||
void canvas_item_add_clip_ignore(RID p_item, bool p_ignore);
|
||||
void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable);
|
||||
void canvas_item_set_z_index(RID p_item, int p_z);
|
||||
void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable);
|
||||
void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect);
|
||||
void canvas_item_attach_skeleton(RID p_item, RID p_skeleton);
|
||||
|
||||
void canvas_item_clear(RID p_item);
|
||||
void canvas_item_set_draw_index(RID p_item, int p_index);
|
||||
|
||||
void canvas_item_set_material(RID p_item, RID p_material);
|
||||
|
||||
void canvas_item_set_use_parent_material(RID p_item, bool p_enable);
|
||||
|
||||
RID canvas_light_create();
|
||||
void canvas_light_attach_to_canvas(RID p_light, RID p_canvas);
|
||||
void canvas_light_set_enabled(RID p_light, bool p_enabled);
|
||||
void canvas_light_set_scale(RID p_light, float p_scale);
|
||||
void canvas_light_set_transform(RID p_light, const Transform2D &p_transform);
|
||||
void canvas_light_set_texture(RID p_light, RID p_texture);
|
||||
void canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset);
|
||||
void canvas_light_set_color(RID p_light, const Color &p_color);
|
||||
void canvas_light_set_height(RID p_light, float p_height);
|
||||
void canvas_light_set_energy(RID p_light, float p_energy);
|
||||
void canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z);
|
||||
void canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer);
|
||||
void canvas_light_set_item_cull_mask(RID p_light, int p_mask);
|
||||
void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask);
|
||||
|
||||
void canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode);
|
||||
|
||||
void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled);
|
||||
void canvas_light_set_shadow_buffer_size(RID p_light, int p_size);
|
||||
void canvas_light_set_shadow_filter(RID p_light, RS::CanvasLightShadowFilter p_filter);
|
||||
void canvas_light_set_shadow_color(RID p_light, const Color &p_color);
|
||||
void canvas_light_set_shadow_smooth(RID p_light, float p_smooth);
|
||||
|
||||
RID canvas_light_occluder_create();
|
||||
void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas);
|
||||
void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled);
|
||||
void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon);
|
||||
void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform);
|
||||
void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask);
|
||||
|
||||
RID canvas_occluder_polygon_create();
|
||||
void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector<Vector2> &p_shape, bool p_closed);
|
||||
void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector<Vector2> &p_shape);
|
||||
|
||||
void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode);
|
||||
|
||||
bool free(RID p_rid);
|
||||
RenderingServerCanvas();
|
||||
~RenderingServerCanvas();
|
||||
};
|
||||
|
||||
#endif // VISUALSERVERCANVAS_H
|
||||
40
servers/rendering/rendering_server_globals.cpp
Normal file
40
servers/rendering/rendering_server_globals.cpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*************************************************************************/
|
||||
/* rendering_server_globals.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "rendering_server_globals.h"
|
||||
|
||||
RasterizerStorage *RenderingServerGlobals::storage = NULL;
|
||||
RasterizerCanvas *RenderingServerGlobals::canvas_render = NULL;
|
||||
RasterizerScene *RenderingServerGlobals::scene_render = NULL;
|
||||
Rasterizer *RenderingServerGlobals::rasterizer = NULL;
|
||||
|
||||
RenderingServerCanvas *RenderingServerGlobals::canvas = NULL;
|
||||
RenderingServerViewport *RenderingServerGlobals::viewport = NULL;
|
||||
RenderingServerScene *RenderingServerGlobals::scene = NULL;
|
||||
54
servers/rendering/rendering_server_globals.h
Normal file
54
servers/rendering/rendering_server_globals.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*************************************************************************/
|
||||
/* rendering_server_globals.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef RENDERING_SERVER_GLOBALS_H
|
||||
#define RENDERING_SERVER_GLOBALS_H
|
||||
|
||||
#include "rasterizer.h"
|
||||
|
||||
class RenderingServerCanvas;
|
||||
class RenderingServerViewport;
|
||||
class RenderingServerScene;
|
||||
|
||||
class RenderingServerGlobals {
|
||||
public:
|
||||
static RasterizerStorage *storage;
|
||||
static RasterizerCanvas *canvas_render;
|
||||
static RasterizerScene *scene_render;
|
||||
static Rasterizer *rasterizer;
|
||||
|
||||
static RenderingServerCanvas *canvas;
|
||||
static RenderingServerViewport *viewport;
|
||||
static RenderingServerScene *scene;
|
||||
};
|
||||
|
||||
#define RSG RenderingServerGlobals
|
||||
|
||||
#endif // RENDERING_SERVER_GLOBALS_H
|
||||
271
servers/rendering/rendering_server_raster.cpp
Normal file
271
servers/rendering/rendering_server_raster.cpp
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
/*************************************************************************/
|
||||
/* rendering_server_raster.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "rendering_server_raster.h"
|
||||
|
||||
#include "core/io/marshalls.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/project_settings.h"
|
||||
#include "core/sort_array.h"
|
||||
#include "rendering_server_canvas.h"
|
||||
#include "rendering_server_globals.h"
|
||||
#include "rendering_server_scene.h"
|
||||
|
||||
// careful, these may run in different threads than the visual server
|
||||
|
||||
int RenderingServerRaster::changes = 0;
|
||||
|
||||
/* BLACK BARS */
|
||||
|
||||
void RenderingServerRaster::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) {
|
||||
|
||||
black_margin[MARGIN_LEFT] = p_left;
|
||||
black_margin[MARGIN_TOP] = p_top;
|
||||
black_margin[MARGIN_RIGHT] = p_right;
|
||||
black_margin[MARGIN_BOTTOM] = p_bottom;
|
||||
}
|
||||
|
||||
void RenderingServerRaster::black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) {
|
||||
|
||||
black_image[MARGIN_LEFT] = p_left;
|
||||
black_image[MARGIN_TOP] = p_top;
|
||||
black_image[MARGIN_RIGHT] = p_right;
|
||||
black_image[MARGIN_BOTTOM] = p_bottom;
|
||||
}
|
||||
|
||||
void RenderingServerRaster::_draw_margins() {
|
||||
|
||||
RSG::canvas_render->draw_window_margins(black_margin, black_image);
|
||||
};
|
||||
|
||||
/* FREE */
|
||||
|
||||
void RenderingServerRaster::free(RID p_rid) {
|
||||
|
||||
if (RSG::storage->free(p_rid))
|
||||
return;
|
||||
if (RSG::canvas->free(p_rid))
|
||||
return;
|
||||
if (RSG::viewport->free(p_rid))
|
||||
return;
|
||||
if (RSG::scene->free(p_rid))
|
||||
return;
|
||||
if (RSG::scene_render->free(p_rid))
|
||||
return;
|
||||
}
|
||||
|
||||
/* EVENT QUEUING */
|
||||
|
||||
void RenderingServerRaster::request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) {
|
||||
|
||||
ERR_FAIL_NULL(p_where);
|
||||
FrameDrawnCallbacks fdc;
|
||||
fdc.object = p_where->get_instance_id();
|
||||
fdc.method = p_method;
|
||||
fdc.param = p_userdata;
|
||||
|
||||
frame_drawn_callbacks.push_back(fdc);
|
||||
}
|
||||
|
||||
void RenderingServerRaster::draw(bool p_swap_buffers, double frame_step) {
|
||||
|
||||
//needs to be done before changes is reset to 0, to not force the editor to redraw
|
||||
RS::get_singleton()->emit_signal("frame_pre_draw");
|
||||
|
||||
changes = 0;
|
||||
|
||||
RSG::rasterizer->begin_frame(frame_step);
|
||||
|
||||
TIMESTAMP_BEGIN()
|
||||
|
||||
RSG::scene_render->update(); //update scenes stuff before updating instances
|
||||
|
||||
RSG::scene->update_dirty_instances(); //update scene stuff
|
||||
|
||||
RSG::scene->render_probes();
|
||||
RSG::viewport->draw_viewports();
|
||||
RSG::canvas_render->update();
|
||||
|
||||
_draw_margins();
|
||||
RSG::rasterizer->end_frame(p_swap_buffers);
|
||||
|
||||
while (frame_drawn_callbacks.front()) {
|
||||
|
||||
Object *obj = ObjectDB::get_instance(frame_drawn_callbacks.front()->get().object);
|
||||
if (obj) {
|
||||
Callable::CallError ce;
|
||||
const Variant *v = &frame_drawn_callbacks.front()->get().param;
|
||||
obj->call(frame_drawn_callbacks.front()->get().method, &v, 1, ce);
|
||||
if (ce.error != Callable::CallError::CALL_OK) {
|
||||
String err = Variant::get_call_error_text(obj, frame_drawn_callbacks.front()->get().method, &v, 1, ce);
|
||||
ERR_PRINT("Error calling frame drawn function: " + err);
|
||||
}
|
||||
}
|
||||
|
||||
frame_drawn_callbacks.pop_front();
|
||||
}
|
||||
RS::get_singleton()->emit_signal("frame_post_draw");
|
||||
|
||||
if (RSG::storage->get_captured_timestamps_count()) {
|
||||
Vector<FrameProfileArea> new_profile;
|
||||
new_profile.resize(RSG::storage->get_captured_timestamps_count());
|
||||
|
||||
uint64_t base_cpu = RSG::storage->get_captured_timestamp_cpu_time(0);
|
||||
uint64_t base_gpu = RSG::storage->get_captured_timestamp_gpu_time(0);
|
||||
for (uint32_t i = 0; i < RSG::storage->get_captured_timestamps_count(); i++) {
|
||||
uint64_t time_cpu = RSG::storage->get_captured_timestamp_cpu_time(i) - base_cpu;
|
||||
uint64_t time_gpu = RSG::storage->get_captured_timestamp_gpu_time(i) - base_gpu;
|
||||
new_profile.write[i].gpu_msec = float(time_gpu / 1000) / 1000.0;
|
||||
new_profile.write[i].cpu_msec = float(time_cpu) / 1000.0;
|
||||
new_profile.write[i].name = RSG::storage->get_captured_timestamp_name(i);
|
||||
}
|
||||
|
||||
frame_profile = new_profile;
|
||||
}
|
||||
|
||||
frame_profile_frame = RSG::storage->get_captured_timestamps_frame();
|
||||
}
|
||||
void RenderingServerRaster::sync() {
|
||||
}
|
||||
bool RenderingServerRaster::has_changed() const {
|
||||
|
||||
return changes > 0;
|
||||
}
|
||||
void RenderingServerRaster::init() {
|
||||
|
||||
RSG::rasterizer->initialize();
|
||||
}
|
||||
void RenderingServerRaster::finish() {
|
||||
|
||||
if (test_cube.is_valid()) {
|
||||
free(test_cube);
|
||||
}
|
||||
|
||||
RSG::rasterizer->finalize();
|
||||
}
|
||||
|
||||
/* STATUS INFORMATION */
|
||||
|
||||
int RenderingServerRaster::get_render_info(RenderInfo p_info) {
|
||||
|
||||
return RSG::storage->get_render_info(p_info);
|
||||
}
|
||||
|
||||
String RenderingServerRaster::get_video_adapter_name() const {
|
||||
|
||||
return RSG::storage->get_video_adapter_name();
|
||||
}
|
||||
|
||||
String RenderingServerRaster::get_video_adapter_vendor() const {
|
||||
|
||||
return RSG::storage->get_video_adapter_vendor();
|
||||
}
|
||||
|
||||
void RenderingServerRaster::set_frame_profiling_enabled(bool p_enable) {
|
||||
RSG::storage->capturing_timestamps = p_enable;
|
||||
}
|
||||
|
||||
uint64_t RenderingServerRaster::get_frame_profile_frame() {
|
||||
return frame_profile_frame;
|
||||
}
|
||||
|
||||
Vector<RenderingServer::FrameProfileArea> RenderingServerRaster::get_frame_profile() {
|
||||
return frame_profile;
|
||||
}
|
||||
|
||||
/* TESTING */
|
||||
|
||||
void RenderingServerRaster::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {
|
||||
|
||||
redraw_request();
|
||||
RSG::rasterizer->set_boot_image(p_image, p_color, p_scale, p_use_filter);
|
||||
}
|
||||
void RenderingServerRaster::set_default_clear_color(const Color &p_color) {
|
||||
RSG::viewport->set_default_clear_color(p_color);
|
||||
}
|
||||
|
||||
bool RenderingServerRaster::has_feature(Features p_feature) const {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
RID RenderingServerRaster::get_test_cube() {
|
||||
if (!test_cube.is_valid()) {
|
||||
test_cube = _make_test_cube();
|
||||
}
|
||||
return test_cube;
|
||||
}
|
||||
|
||||
bool RenderingServerRaster::has_os_feature(const String &p_feature) const {
|
||||
|
||||
return RSG::storage->has_os_feature(p_feature);
|
||||
}
|
||||
|
||||
void RenderingServerRaster::set_debug_generate_wireframes(bool p_generate) {
|
||||
|
||||
RSG::storage->set_debug_generate_wireframes(p_generate);
|
||||
}
|
||||
|
||||
void RenderingServerRaster::call_set_use_vsync(bool p_enable) {
|
||||
DisplayServer::get_singleton()->_set_use_vsync(p_enable);
|
||||
}
|
||||
|
||||
bool RenderingServerRaster::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;
|
||||
}
|
||||
RenderingServerRaster::RenderingServerRaster() {
|
||||
|
||||
RSG::canvas = memnew(RenderingServerCanvas);
|
||||
RSG::viewport = memnew(RenderingServerViewport);
|
||||
RSG::scene = memnew(RenderingServerScene);
|
||||
RSG::rasterizer = Rasterizer::create();
|
||||
RSG::storage = RSG::rasterizer->get_storage();
|
||||
RSG::canvas_render = RSG::rasterizer->get_canvas();
|
||||
RSG::scene_render = RSG::rasterizer->get_scene();
|
||||
|
||||
frame_profile_frame = 0;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
black_margin[i] = 0;
|
||||
black_image[i] = RID();
|
||||
}
|
||||
}
|
||||
|
||||
RenderingServerRaster::~RenderingServerRaster() {
|
||||
|
||||
memdelete(RSG::canvas);
|
||||
memdelete(RSG::viewport);
|
||||
memdelete(RSG::rasterizer);
|
||||
memdelete(RSG::scene);
|
||||
}
|
||||
761
servers/rendering/rendering_server_raster.h
Normal file
761
servers/rendering/rendering_server_raster.h
Normal file
|
|
@ -0,0 +1,761 @@
|
|||
/*************************************************************************/
|
||||
/* rendering_server_raster.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef RENDERING_SERVER_RASTER_H
|
||||
#define RENDERING_SERVER_RASTER_H
|
||||
|
||||
#include "core/math/octree.h"
|
||||
#include "rendering_server_canvas.h"
|
||||
#include "rendering_server_globals.h"
|
||||
#include "rendering_server_scene.h"
|
||||
#include "rendering_server_viewport.h"
|
||||
#include "servers/rendering/rasterizer.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
class RenderingServerRaster : public RenderingServer {
|
||||
|
||||
enum {
|
||||
|
||||
MAX_INSTANCE_CULL = 8192,
|
||||
MAX_INSTANCE_LIGHTS = 4,
|
||||
LIGHT_CACHE_DIRTY = -1,
|
||||
MAX_LIGHTS_CULLED = 256,
|
||||
MAX_ROOM_CULL = 32,
|
||||
MAX_EXTERIOR_PORTALS = 128,
|
||||
MAX_LIGHT_SAMPLERS = 256,
|
||||
INSTANCE_ROOMLESS_MASK = (1 << 20)
|
||||
|
||||
};
|
||||
|
||||
static int changes;
|
||||
RID test_cube;
|
||||
|
||||
int black_margin[4];
|
||||
RID black_image[4];
|
||||
|
||||
struct FrameDrawnCallbacks {
|
||||
|
||||
ObjectID object;
|
||||
StringName method;
|
||||
Variant param;
|
||||
};
|
||||
|
||||
List<FrameDrawnCallbacks> frame_drawn_callbacks;
|
||||
|
||||
void _draw_margins();
|
||||
static void _changes_changed() {}
|
||||
|
||||
uint64_t frame_profile_frame;
|
||||
Vector<FrameProfileArea> frame_profile;
|
||||
|
||||
public:
|
||||
//if editor is redrawing when it shouldn't, enable this and put a breakpoint in _changes_changed()
|
||||
//#define DEBUG_CHANGES
|
||||
|
||||
#ifdef DEBUG_CHANGES
|
||||
_FORCE_INLINE_ static void redraw_request() {
|
||||
changes++;
|
||||
_changes_changed();
|
||||
}
|
||||
|
||||
#define DISPLAY_CHANGED \
|
||||
changes++; \
|
||||
_changes_changed();
|
||||
|
||||
#else
|
||||
_FORCE_INLINE_ static void redraw_request() { changes++; }
|
||||
|
||||
#define DISPLAY_CHANGED \
|
||||
changes++;
|
||||
#endif
|
||||
|
||||
#define BIND0R(m_r, m_name) \
|
||||
m_r m_name() { return BINDBASE->m_name(); }
|
||||
#define BIND1R(m_r, m_name, m_type1) \
|
||||
m_r m_name(m_type1 arg1) { return BINDBASE->m_name(arg1); }
|
||||
#define BIND1RC(m_r, m_name, m_type1) \
|
||||
m_r m_name(m_type1 arg1) const { return BINDBASE->m_name(arg1); }
|
||||
#define BIND2R(m_r, m_name, m_type1, m_type2) \
|
||||
m_r m_name(m_type1 arg1, m_type2 arg2) { return BINDBASE->m_name(arg1, arg2); }
|
||||
#define BIND2RC(m_r, m_name, m_type1, m_type2) \
|
||||
m_r m_name(m_type1 arg1, m_type2 arg2) const { return BINDBASE->m_name(arg1, arg2); }
|
||||
#define BIND3RC(m_r, m_name, m_type1, m_type2, m_type3) \
|
||||
m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) const { return BINDBASE->m_name(arg1, arg2, arg3); }
|
||||
#define BIND4RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \
|
||||
m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4); }
|
||||
|
||||
#define BIND1(m_name, m_type1) \
|
||||
void m_name(m_type1 arg1) { DISPLAY_CHANGED BINDBASE->m_name(arg1); }
|
||||
#define BIND2(m_name, m_type1, m_type2) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2); }
|
||||
#define BIND2C(m_name, m_type1, m_type2) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2) const { BINDBASE->m_name(arg1, arg2); }
|
||||
#define BIND3(m_name, m_type1, m_type2, m_type3) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3); }
|
||||
#define BIND4(m_name, m_type1, m_type2, m_type3, m_type4) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4); }
|
||||
#define BIND5(m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5); }
|
||||
#define BIND6(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); }
|
||||
#define BIND7(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7); }
|
||||
#define BIND8(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); }
|
||||
#define BIND9(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); }
|
||||
#define BIND10(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); }
|
||||
#define BIND11(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); }
|
||||
#define BIND12(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); }
|
||||
#define BIND13(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); }
|
||||
#define BIND14(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13, m_type14) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13, m_type14 arg14) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); }
|
||||
#define BIND15(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13, m_type14, m_type15) \
|
||||
void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13, m_type14 arg14, m_type15 arg15) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); }
|
||||
|
||||
//from now on, calls forwarded to this singleton
|
||||
#define BINDBASE RSG::storage
|
||||
|
||||
/* TEXTURE API */
|
||||
|
||||
//these go pass-through, as they can be called from any thread
|
||||
BIND1R(RID, texture_2d_create, const Ref<Image> &)
|
||||
BIND2R(RID, texture_2d_layered_create, const Vector<Ref<Image>> &, TextureLayeredType)
|
||||
BIND1R(RID, texture_3d_create, const Vector<Ref<Image>> &)
|
||||
BIND1R(RID, texture_proxy_create, RID)
|
||||
|
||||
//goes pass-through
|
||||
BIND3(texture_2d_update_immediate, RID, const Ref<Image> &, int)
|
||||
//these go through command queue if they are in another thread
|
||||
BIND3(texture_2d_update, RID, const Ref<Image> &, int)
|
||||
BIND4(texture_3d_update, RID, const Ref<Image> &, int, int)
|
||||
BIND2(texture_proxy_update, RID, RID)
|
||||
|
||||
//these also go pass-through
|
||||
BIND0R(RID, texture_2d_placeholder_create)
|
||||
BIND0R(RID, texture_2d_layered_placeholder_create)
|
||||
BIND0R(RID, texture_3d_placeholder_create)
|
||||
|
||||
BIND1RC(Ref<Image>, texture_2d_get, RID)
|
||||
BIND2RC(Ref<Image>, texture_2d_layer_get, RID, int)
|
||||
BIND3RC(Ref<Image>, texture_3d_slice_get, RID, int, int)
|
||||
|
||||
BIND2(texture_replace, RID, RID)
|
||||
|
||||
BIND3(texture_set_size_override, RID, int, int)
|
||||
// FIXME: Disabled during Vulkan refactoring, should be ported.
|
||||
#if 0
|
||||
BIND2(texture_bind, RID, uint32_t)
|
||||
#endif
|
||||
|
||||
BIND3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
|
||||
BIND3(texture_set_detect_normal_callback, RID, TextureDetectCallback, void *)
|
||||
BIND3(texture_set_detect_roughness_callback, RID, TextureDetectRoughnessCallback, void *)
|
||||
|
||||
BIND2(texture_set_path, RID, const String &)
|
||||
BIND1RC(String, texture_get_path, RID)
|
||||
BIND1(texture_debug_usage, List<TextureInfo> *)
|
||||
|
||||
BIND2(texture_set_force_redraw_if_visible, RID, bool)
|
||||
|
||||
/* SHADER API */
|
||||
|
||||
BIND0R(RID, shader_create)
|
||||
|
||||
BIND2(shader_set_code, RID, const String &)
|
||||
BIND1RC(String, shader_get_code, RID)
|
||||
|
||||
BIND2C(shader_get_param_list, RID, List<PropertyInfo> *)
|
||||
|
||||
BIND3(shader_set_default_texture_param, RID, const StringName &, RID)
|
||||
BIND2RC(RID, shader_get_default_texture_param, RID, const StringName &)
|
||||
BIND2RC(Variant, shader_get_param_default, RID, const StringName &)
|
||||
|
||||
/* COMMON MATERIAL API */
|
||||
|
||||
BIND0R(RID, material_create)
|
||||
|
||||
BIND2(material_set_shader, RID, RID)
|
||||
|
||||
BIND3(material_set_param, RID, const StringName &, const Variant &)
|
||||
BIND2RC(Variant, material_get_param, RID, const StringName &)
|
||||
|
||||
BIND2(material_set_render_priority, RID, int)
|
||||
BIND2(material_set_next_pass, RID, RID)
|
||||
|
||||
/* MESH API */
|
||||
|
||||
virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces) {
|
||||
RID mesh = mesh_create();
|
||||
for (int i = 0; i < p_surfaces.size(); i++) {
|
||||
mesh_add_surface(mesh, p_surfaces[i]);
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
BIND0R(RID, mesh_create)
|
||||
|
||||
BIND2(mesh_add_surface, RID, const SurfaceData &)
|
||||
|
||||
BIND1RC(int, mesh_get_blend_shape_count, RID)
|
||||
|
||||
BIND2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
|
||||
BIND1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID)
|
||||
|
||||
BIND4(mesh_surface_update_region, RID, int, int, const Vector<uint8_t> &)
|
||||
|
||||
BIND3(mesh_surface_set_material, RID, int, RID)
|
||||
BIND2RC(RID, mesh_surface_get_material, RID, int)
|
||||
|
||||
BIND2RC(SurfaceData, mesh_get_surface, RID, int)
|
||||
|
||||
BIND1RC(int, mesh_get_surface_count, RID)
|
||||
|
||||
BIND2(mesh_set_custom_aabb, RID, const AABB &)
|
||||
BIND1RC(AABB, mesh_get_custom_aabb, RID)
|
||||
|
||||
BIND1(mesh_clear, RID)
|
||||
|
||||
/* MULTIMESH API */
|
||||
|
||||
BIND0R(RID, multimesh_create)
|
||||
|
||||
BIND5(multimesh_allocate, RID, int, MultimeshTransformFormat, bool, bool)
|
||||
BIND1RC(int, multimesh_get_instance_count, RID)
|
||||
|
||||
BIND2(multimesh_set_mesh, RID, RID)
|
||||
BIND3(multimesh_instance_set_transform, RID, int, const Transform &)
|
||||
BIND3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &)
|
||||
BIND3(multimesh_instance_set_color, RID, int, const Color &)
|
||||
BIND3(multimesh_instance_set_custom_data, RID, int, const Color &)
|
||||
|
||||
BIND1RC(RID, multimesh_get_mesh, RID)
|
||||
BIND1RC(AABB, multimesh_get_aabb, RID)
|
||||
|
||||
BIND2RC(Transform, multimesh_instance_get_transform, RID, int)
|
||||
BIND2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
|
||||
BIND2RC(Color, multimesh_instance_get_color, RID, int)
|
||||
BIND2RC(Color, multimesh_instance_get_custom_data, RID, int)
|
||||
|
||||
BIND2(multimesh_set_buffer, RID, const Vector<float> &)
|
||||
BIND1RC(Vector<float>, multimesh_get_buffer, RID)
|
||||
|
||||
BIND2(multimesh_set_visible_instances, RID, int)
|
||||
BIND1RC(int, multimesh_get_visible_instances, RID)
|
||||
|
||||
/* IMMEDIATE API */
|
||||
|
||||
BIND0R(RID, immediate_create)
|
||||
BIND3(immediate_begin, RID, PrimitiveType, RID)
|
||||
BIND2(immediate_vertex, RID, const Vector3 &)
|
||||
BIND2(immediate_normal, RID, const Vector3 &)
|
||||
BIND2(immediate_tangent, RID, const Plane &)
|
||||
BIND2(immediate_color, RID, const Color &)
|
||||
BIND2(immediate_uv, RID, const Vector2 &)
|
||||
BIND2(immediate_uv2, RID, const Vector2 &)
|
||||
BIND1(immediate_end, RID)
|
||||
BIND1(immediate_clear, RID)
|
||||
BIND2(immediate_set_material, RID, RID)
|
||||
BIND1RC(RID, immediate_get_material, RID)
|
||||
|
||||
/* SKELETON API */
|
||||
|
||||
BIND0R(RID, skeleton_create)
|
||||
BIND3(skeleton_allocate, RID, int, bool)
|
||||
BIND1RC(int, skeleton_get_bone_count, RID)
|
||||
BIND3(skeleton_bone_set_transform, RID, int, const Transform &)
|
||||
BIND2RC(Transform, skeleton_bone_get_transform, RID, int)
|
||||
BIND3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &)
|
||||
BIND2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int)
|
||||
BIND2(skeleton_set_base_transform_2d, RID, const Transform2D &)
|
||||
|
||||
/* Light API */
|
||||
|
||||
BIND0R(RID, directional_light_create)
|
||||
BIND0R(RID, omni_light_create)
|
||||
BIND0R(RID, spot_light_create)
|
||||
|
||||
BIND2(light_set_color, RID, const Color &)
|
||||
BIND3(light_set_param, RID, LightParam, float)
|
||||
BIND2(light_set_shadow, RID, bool)
|
||||
BIND2(light_set_shadow_color, RID, const Color &)
|
||||
BIND2(light_set_projector, RID, RID)
|
||||
BIND2(light_set_negative, RID, bool)
|
||||
BIND2(light_set_cull_mask, RID, uint32_t)
|
||||
BIND2(light_set_reverse_cull_face_mode, RID, bool)
|
||||
BIND2(light_set_use_gi, RID, bool)
|
||||
|
||||
BIND2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
|
||||
|
||||
BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
|
||||
BIND2(light_directional_set_blend_splits, RID, bool)
|
||||
BIND2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
|
||||
|
||||
/* PROBE API */
|
||||
|
||||
BIND0R(RID, reflection_probe_create)
|
||||
|
||||
BIND2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode)
|
||||
BIND2(reflection_probe_set_intensity, RID, float)
|
||||
BIND2(reflection_probe_set_interior_ambient, RID, const Color &)
|
||||
BIND2(reflection_probe_set_interior_ambient_energy, RID, float)
|
||||
BIND2(reflection_probe_set_interior_ambient_probe_contribution, RID, float)
|
||||
BIND2(reflection_probe_set_max_distance, RID, float)
|
||||
BIND2(reflection_probe_set_extents, RID, const Vector3 &)
|
||||
BIND2(reflection_probe_set_origin_offset, RID, const Vector3 &)
|
||||
BIND2(reflection_probe_set_as_interior, RID, bool)
|
||||
BIND2(reflection_probe_set_enable_box_projection, RID, bool)
|
||||
BIND2(reflection_probe_set_enable_shadows, RID, bool)
|
||||
BIND2(reflection_probe_set_cull_mask, RID, uint32_t)
|
||||
BIND2(reflection_probe_set_resolution, RID, int)
|
||||
|
||||
/* BAKED LIGHT API */
|
||||
|
||||
BIND0R(RID, gi_probe_create)
|
||||
|
||||
BIND8(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<int> &)
|
||||
|
||||
BIND1RC(AABB, gi_probe_get_bounds, RID)
|
||||
BIND1RC(Vector3i, gi_probe_get_octree_size, RID)
|
||||
BIND1RC(Vector<uint8_t>, gi_probe_get_octree_cells, RID)
|
||||
BIND1RC(Vector<uint8_t>, gi_probe_get_data_cells, RID)
|
||||
BIND1RC(Vector<uint8_t>, gi_probe_get_distance_field, RID)
|
||||
BIND1RC(Vector<int>, gi_probe_get_level_counts, RID)
|
||||
BIND1RC(Transform, gi_probe_get_to_cell_xform, RID)
|
||||
|
||||
BIND2(gi_probe_set_dynamic_range, RID, float)
|
||||
BIND1RC(float, gi_probe_get_dynamic_range, RID)
|
||||
|
||||
BIND2(gi_probe_set_propagation, RID, float)
|
||||
BIND1RC(float, gi_probe_get_propagation, RID)
|
||||
|
||||
BIND2(gi_probe_set_energy, RID, float)
|
||||
BIND1RC(float, gi_probe_get_energy, RID)
|
||||
|
||||
BIND2(gi_probe_set_ao, RID, float)
|
||||
BIND1RC(float, gi_probe_get_ao, RID)
|
||||
|
||||
BIND2(gi_probe_set_ao_size, RID, float)
|
||||
BIND1RC(float, gi_probe_get_ao_size, RID)
|
||||
|
||||
BIND2(gi_probe_set_bias, RID, float)
|
||||
BIND1RC(float, gi_probe_get_bias, RID)
|
||||
|
||||
BIND2(gi_probe_set_normal_bias, RID, float)
|
||||
BIND1RC(float, gi_probe_get_normal_bias, RID)
|
||||
|
||||
BIND2(gi_probe_set_interior, RID, bool)
|
||||
BIND1RC(bool, gi_probe_is_interior, RID)
|
||||
|
||||
BIND2(gi_probe_set_use_two_bounces, RID, bool)
|
||||
BIND1RC(bool, gi_probe_is_using_two_bounces, RID)
|
||||
|
||||
BIND2(gi_probe_set_anisotropy_strength, RID, float)
|
||||
BIND1RC(float, gi_probe_get_anisotropy_strength, RID)
|
||||
|
||||
/* LIGHTMAP CAPTURE */
|
||||
|
||||
BIND0R(RID, lightmap_capture_create)
|
||||
|
||||
BIND2(lightmap_capture_set_bounds, RID, const AABB &)
|
||||
BIND1RC(AABB, lightmap_capture_get_bounds, RID)
|
||||
|
||||
BIND2(lightmap_capture_set_octree, RID, const Vector<uint8_t> &)
|
||||
BIND1RC(Vector<uint8_t>, lightmap_capture_get_octree, RID)
|
||||
|
||||
BIND2(lightmap_capture_set_octree_cell_transform, RID, const Transform &)
|
||||
BIND1RC(Transform, lightmap_capture_get_octree_cell_transform, RID)
|
||||
BIND2(lightmap_capture_set_octree_cell_subdiv, RID, int)
|
||||
BIND1RC(int, lightmap_capture_get_octree_cell_subdiv, RID)
|
||||
|
||||
BIND2(lightmap_capture_set_energy, RID, float)
|
||||
BIND1RC(float, lightmap_capture_get_energy, RID)
|
||||
|
||||
/* PARTICLES */
|
||||
|
||||
BIND0R(RID, particles_create)
|
||||
|
||||
BIND2(particles_set_emitting, RID, bool)
|
||||
BIND1R(bool, particles_get_emitting, RID)
|
||||
BIND2(particles_set_amount, RID, int)
|
||||
BIND2(particles_set_lifetime, RID, float)
|
||||
BIND2(particles_set_one_shot, RID, bool)
|
||||
BIND2(particles_set_pre_process_time, RID, float)
|
||||
BIND2(particles_set_explosiveness_ratio, RID, float)
|
||||
BIND2(particles_set_randomness_ratio, RID, float)
|
||||
BIND2(particles_set_custom_aabb, RID, const AABB &)
|
||||
BIND2(particles_set_speed_scale, RID, float)
|
||||
BIND2(particles_set_use_local_coordinates, RID, bool)
|
||||
BIND2(particles_set_process_material, RID, RID)
|
||||
BIND2(particles_set_fixed_fps, RID, int)
|
||||
BIND2(particles_set_fractional_delta, RID, bool)
|
||||
BIND1R(bool, particles_is_inactive, RID)
|
||||
BIND1(particles_request_process, RID)
|
||||
BIND1(particles_restart, RID)
|
||||
|
||||
BIND2(particles_set_draw_order, RID, RS::ParticlesDrawOrder)
|
||||
|
||||
BIND2(particles_set_draw_passes, RID, int)
|
||||
BIND3(particles_set_draw_pass_mesh, RID, int, RID)
|
||||
|
||||
BIND1R(AABB, particles_get_current_aabb, RID)
|
||||
BIND2(particles_set_emission_transform, RID, const Transform &)
|
||||
|
||||
#undef BINDBASE
|
||||
//from now on, calls forwarded to this singleton
|
||||
#define BINDBASE RSG::scene
|
||||
|
||||
/* CAMERA API */
|
||||
|
||||
BIND0R(RID, camera_create)
|
||||
BIND4(camera_set_perspective, RID, float, float, float)
|
||||
BIND4(camera_set_orthogonal, RID, float, float, float)
|
||||
BIND5(camera_set_frustum, RID, float, Vector2, float, float)
|
||||
BIND2(camera_set_transform, RID, const Transform &)
|
||||
BIND2(camera_set_cull_mask, RID, uint32_t)
|
||||
BIND2(camera_set_environment, RID, RID)
|
||||
BIND2(camera_set_camera_effects, RID, RID)
|
||||
BIND2(camera_set_use_vertical_aspect, RID, bool)
|
||||
|
||||
#undef BINDBASE
|
||||
//from now on, calls forwarded to this singleton
|
||||
#define BINDBASE RSG::viewport
|
||||
|
||||
/* VIEWPORT TARGET API */
|
||||
|
||||
BIND0R(RID, viewport_create)
|
||||
|
||||
BIND2(viewport_set_use_arvr, RID, bool)
|
||||
BIND3(viewport_set_size, RID, int, int)
|
||||
|
||||
BIND2(viewport_set_active, RID, bool)
|
||||
BIND2(viewport_set_parent_viewport, RID, RID)
|
||||
|
||||
BIND2(viewport_set_clear_mode, RID, ViewportClearMode)
|
||||
|
||||
BIND3(viewport_attach_to_screen, RID, const Rect2 &, int)
|
||||
BIND2(viewport_set_render_direct_to_screen, RID, bool)
|
||||
|
||||
BIND2(viewport_set_update_mode, RID, ViewportUpdateMode)
|
||||
BIND2(viewport_set_vflip, RID, bool)
|
||||
|
||||
BIND1RC(RID, viewport_get_texture, RID)
|
||||
|
||||
BIND2(viewport_set_hide_scenario, RID, bool)
|
||||
BIND2(viewport_set_hide_canvas, RID, bool)
|
||||
BIND2(viewport_set_disable_environment, RID, bool)
|
||||
|
||||
BIND2(viewport_attach_camera, RID, RID)
|
||||
BIND2(viewport_set_scenario, RID, RID)
|
||||
BIND2(viewport_attach_canvas, RID, RID)
|
||||
|
||||
BIND2(viewport_remove_canvas, RID, RID)
|
||||
BIND3(viewport_set_canvas_transform, RID, RID, const Transform2D &)
|
||||
BIND2(viewport_set_transparent_background, RID, bool)
|
||||
|
||||
BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &)
|
||||
BIND4(viewport_set_canvas_stacking, RID, RID, int, int)
|
||||
BIND2(viewport_set_shadow_atlas_size, RID, int)
|
||||
BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
|
||||
BIND2(viewport_set_msaa, RID, ViewportMSAA)
|
||||
|
||||
BIND2R(int, viewport_get_render_info, RID, ViewportRenderInfo)
|
||||
BIND2(viewport_set_debug_draw, RID, ViewportDebugDraw)
|
||||
|
||||
/* ENVIRONMENT API */
|
||||
|
||||
#undef BINDBASE
|
||||
//from now on, calls forwarded to this singleton
|
||||
#define BINDBASE RSG::scene_render
|
||||
|
||||
BIND1(directional_shadow_atlas_set_size, int)
|
||||
|
||||
/* SKY API */
|
||||
|
||||
BIND0R(RID, sky_create)
|
||||
BIND2(sky_set_radiance_size, RID, int)
|
||||
BIND2(sky_set_mode, RID, SkyMode)
|
||||
BIND2(sky_set_material, RID, RID)
|
||||
|
||||
BIND0R(RID, environment_create)
|
||||
|
||||
BIND2(environment_set_background, RID, EnvironmentBG)
|
||||
BIND2(environment_set_sky, RID, RID)
|
||||
BIND2(environment_set_sky_custom_fov, RID, float)
|
||||
BIND2(environment_set_sky_orientation, RID, const Basis &)
|
||||
BIND2(environment_set_bg_color, RID, const Color &)
|
||||
BIND2(environment_set_bg_energy, RID, float)
|
||||
BIND2(environment_set_canvas_max_layer, RID, int)
|
||||
BIND7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &)
|
||||
|
||||
// FIXME: Disabled during Vulkan refactoring, should be ported.
|
||||
#if 0
|
||||
BIND2(environment_set_camera_feed_id, RID, int)
|
||||
#endif
|
||||
BIND7(environment_set_ssr, RID, bool, int, float, float, float, bool)
|
||||
BIND9(environment_set_ssao, RID, bool, float, float, float, float, float, EnvironmentSSAOBlur, float)
|
||||
BIND2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool)
|
||||
|
||||
BIND12(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool)
|
||||
|
||||
BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
|
||||
|
||||
BIND6(environment_set_adjustment, RID, bool, float, float, float, RID)
|
||||
|
||||
BIND5(environment_set_fog, RID, bool, const Color &, const Color &, float)
|
||||
BIND7(environment_set_fog_depth, RID, bool, float, float, float, bool, float)
|
||||
BIND5(environment_set_fog_height, RID, bool, float, float, float)
|
||||
|
||||
BIND2(screen_space_roughness_limiter_set_active, bool, float)
|
||||
|
||||
/* CAMERA EFFECTS */
|
||||
|
||||
BIND0R(RID, camera_effects_create)
|
||||
|
||||
BIND2(camera_effects_set_dof_blur_quality, DOFBlurQuality, bool)
|
||||
BIND1(camera_effects_set_dof_blur_bokeh_shape, DOFBokehShape)
|
||||
|
||||
BIND8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
|
||||
BIND3(camera_effects_set_custom_exposure, RID, bool, float)
|
||||
|
||||
/* SCENARIO API */
|
||||
|
||||
#undef BINDBASE
|
||||
#define BINDBASE RSG::scene
|
||||
|
||||
BIND0R(RID, scenario_create)
|
||||
|
||||
BIND2(scenario_set_debug, RID, ScenarioDebugMode)
|
||||
BIND2(scenario_set_environment, RID, RID)
|
||||
BIND2(scenario_set_camera_effects, RID, RID)
|
||||
BIND2(scenario_set_fallback_environment, RID, RID)
|
||||
|
||||
/* INSTANCING API */
|
||||
BIND0R(RID, instance_create)
|
||||
|
||||
BIND2(instance_set_base, RID, RID)
|
||||
BIND2(instance_set_scenario, RID, RID)
|
||||
BIND2(instance_set_layer_mask, RID, uint32_t)
|
||||
BIND2(instance_set_transform, RID, const Transform &)
|
||||
BIND2(instance_attach_object_instance_id, RID, ObjectID)
|
||||
BIND3(instance_set_blend_shape_weight, RID, int, float)
|
||||
BIND3(instance_set_surface_material, RID, int, RID)
|
||||
BIND2(instance_set_visible, RID, bool)
|
||||
BIND3(instance_set_use_lightmap, RID, RID, RID)
|
||||
|
||||
BIND2(instance_set_custom_aabb, RID, AABB)
|
||||
|
||||
BIND2(instance_attach_skeleton, RID, RID)
|
||||
BIND2(instance_set_exterior, RID, bool)
|
||||
|
||||
BIND2(instance_set_extra_visibility_margin, RID, real_t)
|
||||
|
||||
// don't use these in a game!
|
||||
BIND2RC(Vector<ObjectID>, instances_cull_aabb, const AABB &, RID)
|
||||
BIND3RC(Vector<ObjectID>, instances_cull_ray, const Vector3 &, const Vector3 &, RID)
|
||||
BIND2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
|
||||
|
||||
BIND3(instance_geometry_set_flag, RID, InstanceFlags, bool)
|
||||
BIND2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
|
||||
BIND2(instance_geometry_set_material_override, RID, RID)
|
||||
|
||||
BIND5(instance_geometry_set_draw_range, RID, float, float, float, float)
|
||||
BIND2(instance_geometry_set_as_instance_lod, RID, RID)
|
||||
|
||||
#undef BINDBASE
|
||||
//from now on, calls forwarded to this singleton
|
||||
#define BINDBASE RSG::canvas
|
||||
|
||||
/* CANVAS (2D) */
|
||||
|
||||
BIND0R(RID, canvas_create)
|
||||
BIND3(canvas_set_item_mirroring, RID, RID, const Point2 &)
|
||||
BIND2(canvas_set_modulate, RID, const Color &)
|
||||
BIND3(canvas_set_parent, RID, RID, float)
|
||||
BIND1(canvas_set_disable_scale, bool)
|
||||
|
||||
BIND0R(RID, canvas_item_create)
|
||||
BIND2(canvas_item_set_parent, RID, RID)
|
||||
|
||||
BIND2(canvas_item_set_visible, RID, bool)
|
||||
BIND2(canvas_item_set_light_mask, RID, int)
|
||||
|
||||
BIND2(canvas_item_set_update_when_visible, RID, bool)
|
||||
|
||||
BIND2(canvas_item_set_transform, RID, const Transform2D &)
|
||||
BIND2(canvas_item_set_clip, RID, bool)
|
||||
BIND2(canvas_item_set_distance_field_mode, RID, bool)
|
||||
BIND3(canvas_item_set_custom_rect, RID, bool, const Rect2 &)
|
||||
BIND2(canvas_item_set_modulate, RID, const Color &)
|
||||
BIND2(canvas_item_set_self_modulate, RID, const Color &)
|
||||
|
||||
BIND2(canvas_item_set_draw_behind_parent, RID, bool)
|
||||
|
||||
BIND2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter)
|
||||
BIND2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat)
|
||||
|
||||
BIND5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float)
|
||||
BIND4(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float)
|
||||
BIND4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
|
||||
BIND3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
|
||||
BIND4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
|
||||
BIND11(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
BIND12(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, RID, RID, const Color &, bool, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
BIND15(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
BIND11(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
BIND10(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
BIND14(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
BIND10(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
BIND8(canvas_item_add_multimesh, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
BIND8(canvas_item_add_particles, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
BIND2(canvas_item_add_set_transform, RID, const Transform2D &)
|
||||
BIND2(canvas_item_add_clip_ignore, RID, bool)
|
||||
BIND2(canvas_item_set_sort_children_by_y, RID, bool)
|
||||
BIND2(canvas_item_set_z_index, RID, int)
|
||||
BIND2(canvas_item_set_z_as_relative_to_parent, RID, bool)
|
||||
BIND3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &)
|
||||
BIND2(canvas_item_attach_skeleton, RID, RID)
|
||||
|
||||
BIND1(canvas_item_clear, RID)
|
||||
BIND2(canvas_item_set_draw_index, RID, int)
|
||||
|
||||
BIND2(canvas_item_set_material, RID, RID)
|
||||
|
||||
BIND2(canvas_item_set_use_parent_material, RID, bool)
|
||||
|
||||
BIND0R(RID, canvas_light_create)
|
||||
BIND2(canvas_light_attach_to_canvas, RID, RID)
|
||||
BIND2(canvas_light_set_enabled, RID, bool)
|
||||
BIND2(canvas_light_set_scale, RID, float)
|
||||
BIND2(canvas_light_set_transform, RID, const Transform2D &)
|
||||
BIND2(canvas_light_set_texture, RID, RID)
|
||||
BIND2(canvas_light_set_texture_offset, RID, const Vector2 &)
|
||||
BIND2(canvas_light_set_color, RID, const Color &)
|
||||
BIND2(canvas_light_set_height, RID, float)
|
||||
BIND2(canvas_light_set_energy, RID, float)
|
||||
BIND3(canvas_light_set_z_range, RID, int, int)
|
||||
BIND3(canvas_light_set_layer_range, RID, int, int)
|
||||
BIND2(canvas_light_set_item_cull_mask, RID, int)
|
||||
BIND2(canvas_light_set_item_shadow_cull_mask, RID, int)
|
||||
|
||||
BIND2(canvas_light_set_mode, RID, CanvasLightMode)
|
||||
|
||||
BIND2(canvas_light_set_shadow_enabled, RID, bool)
|
||||
BIND2(canvas_light_set_shadow_buffer_size, RID, int)
|
||||
BIND2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter)
|
||||
BIND2(canvas_light_set_shadow_color, RID, const Color &)
|
||||
BIND2(canvas_light_set_shadow_smooth, RID, float)
|
||||
|
||||
BIND0R(RID, canvas_light_occluder_create)
|
||||
BIND2(canvas_light_occluder_attach_to_canvas, RID, RID)
|
||||
BIND2(canvas_light_occluder_set_enabled, RID, bool)
|
||||
BIND2(canvas_light_occluder_set_polygon, RID, RID)
|
||||
BIND2(canvas_light_occluder_set_transform, RID, const Transform2D &)
|
||||
BIND2(canvas_light_occluder_set_light_mask, RID, int)
|
||||
|
||||
BIND0R(RID, canvas_occluder_polygon_create)
|
||||
BIND3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool)
|
||||
BIND2(canvas_occluder_polygon_set_shape_as_lines, RID, const Vector<Vector2> &)
|
||||
|
||||
BIND2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
|
||||
|
||||
/* BLACK BARS */
|
||||
|
||||
virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom);
|
||||
virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom);
|
||||
|
||||
/* FREE */
|
||||
|
||||
virtual void free(RID p_rid); ///< free RIDs associated with the visual server
|
||||
|
||||
/* EVENT QUEUING */
|
||||
|
||||
virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata);
|
||||
|
||||
virtual void draw(bool p_swap_buffers, double frame_step);
|
||||
virtual void sync();
|
||||
virtual bool has_changed() const;
|
||||
virtual void init();
|
||||
virtual void finish();
|
||||
|
||||
/* STATUS INFORMATION */
|
||||
|
||||
virtual int get_render_info(RenderInfo p_info);
|
||||
virtual String get_video_adapter_name() const;
|
||||
virtual String get_video_adapter_vendor() const;
|
||||
|
||||
virtual void set_frame_profiling_enabled(bool p_enable);
|
||||
virtual Vector<FrameProfileArea> get_frame_profile();
|
||||
virtual uint64_t get_frame_profile_frame();
|
||||
|
||||
virtual RID get_test_cube();
|
||||
|
||||
/* TESTING */
|
||||
|
||||
virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true);
|
||||
virtual void set_default_clear_color(const Color &p_color);
|
||||
|
||||
virtual bool has_feature(Features p_feature) const;
|
||||
|
||||
virtual bool has_os_feature(const String &p_feature) const;
|
||||
virtual void set_debug_generate_wireframes(bool p_generate);
|
||||
|
||||
virtual void call_set_use_vsync(bool p_enable);
|
||||
|
||||
virtual bool is_low_end() const;
|
||||
|
||||
RenderingServerRaster();
|
||||
~RenderingServerRaster();
|
||||
|
||||
#undef DISPLAY_CHANGED
|
||||
|
||||
#undef BIND0R
|
||||
#undef BIND1RC
|
||||
#undef BIND2RC
|
||||
#undef BIND3RC
|
||||
#undef BIND4RC
|
||||
|
||||
#undef BIND1
|
||||
#undef BIND2
|
||||
#undef BIND3
|
||||
#undef BIND4
|
||||
#undef BIND5
|
||||
#undef BIND6
|
||||
#undef BIND7
|
||||
#undef BIND8
|
||||
#undef BIND9
|
||||
#undef BIND10
|
||||
};
|
||||
|
||||
#endif
|
||||
2839
servers/rendering/rendering_server_scene.cpp
Normal file
2839
servers/rendering/rendering_server_scene.cpp
Normal file
File diff suppressed because it is too large
Load diff
440
servers/rendering/rendering_server_scene.h
Normal file
440
servers/rendering/rendering_server_scene.h
Normal file
|
|
@ -0,0 +1,440 @@
|
|||
/*************************************************************************/
|
||||
/* rendering_server_scene.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef VISUALSERVERSCENE_H
|
||||
#define VISUALSERVERSCENE_H
|
||||
|
||||
#include "servers/rendering/rasterizer.h"
|
||||
|
||||
#include "core/math/geometry.h"
|
||||
#include "core/math/octree.h"
|
||||
#include "core/os/semaphore.h"
|
||||
#include "core/os/thread.h"
|
||||
#include "core/rid_owner.h"
|
||||
#include "core/self_list.h"
|
||||
#include "servers/arvr/arvr_interface.h"
|
||||
|
||||
class RenderingServerScene {
|
||||
public:
|
||||
enum {
|
||||
|
||||
MAX_INSTANCE_CULL = 65536,
|
||||
MAX_LIGHTS_CULLED = 4096,
|
||||
MAX_REFLECTION_PROBES_CULLED = 4096,
|
||||
MAX_GI_PROBES_CULLED = 4096,
|
||||
MAX_ROOM_CULL = 32,
|
||||
MAX_EXTERIOR_PORTALS = 128,
|
||||
};
|
||||
|
||||
uint64_t render_pass;
|
||||
|
||||
static RenderingServerScene *singleton;
|
||||
|
||||
/* CAMERA API */
|
||||
|
||||
struct Camera {
|
||||
|
||||
enum Type {
|
||||
PERSPECTIVE,
|
||||
ORTHOGONAL,
|
||||
FRUSTUM
|
||||
};
|
||||
Type type;
|
||||
float fov;
|
||||
float znear, zfar;
|
||||
float size;
|
||||
Vector2 offset;
|
||||
uint32_t visible_layers;
|
||||
bool vaspect;
|
||||
RID env;
|
||||
RID effects;
|
||||
|
||||
Transform transform;
|
||||
|
||||
Camera() {
|
||||
|
||||
visible_layers = 0xFFFFFFFF;
|
||||
fov = 70;
|
||||
type = PERSPECTIVE;
|
||||
znear = 0.05;
|
||||
zfar = 100;
|
||||
size = 1.0;
|
||||
offset = Vector2();
|
||||
vaspect = false;
|
||||
}
|
||||
};
|
||||
|
||||
mutable RID_PtrOwner<Camera> camera_owner;
|
||||
|
||||
virtual RID camera_create();
|
||||
virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far);
|
||||
virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far);
|
||||
virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far);
|
||||
virtual void camera_set_transform(RID p_camera, const Transform &p_transform);
|
||||
virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers);
|
||||
virtual void camera_set_environment(RID p_camera, RID p_env);
|
||||
virtual void camera_set_camera_effects(RID p_camera, RID p_fx);
|
||||
virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable);
|
||||
|
||||
/* SCENARIO API */
|
||||
|
||||
struct Instance;
|
||||
|
||||
struct Scenario {
|
||||
|
||||
RS::ScenarioDebugMode debug;
|
||||
RID self;
|
||||
|
||||
Octree<Instance, true> octree;
|
||||
|
||||
List<Instance *> directional_lights;
|
||||
RID environment;
|
||||
RID fallback_environment;
|
||||
RID camera_effects;
|
||||
RID reflection_probe_shadow_atlas;
|
||||
RID reflection_atlas;
|
||||
|
||||
SelfList<Instance>::List instances;
|
||||
|
||||
Scenario() { debug = RS::SCENARIO_DEBUG_DISABLED; }
|
||||
};
|
||||
|
||||
mutable RID_PtrOwner<Scenario> scenario_owner;
|
||||
|
||||
static void *_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int);
|
||||
static void _instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *);
|
||||
|
||||
virtual RID scenario_create();
|
||||
|
||||
virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode);
|
||||
virtual void scenario_set_environment(RID p_scenario, RID p_environment);
|
||||
virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx);
|
||||
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment);
|
||||
virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count);
|
||||
|
||||
/* INSTANCING API */
|
||||
|
||||
struct InstanceBaseData {
|
||||
|
||||
virtual ~InstanceBaseData() {}
|
||||
};
|
||||
|
||||
struct Instance : RasterizerScene::InstanceBase {
|
||||
|
||||
RID self;
|
||||
//scenario stuff
|
||||
OctreeElementID octree_id;
|
||||
Scenario *scenario;
|
||||
SelfList<Instance> scenario_item;
|
||||
|
||||
//aabb stuff
|
||||
bool update_aabb;
|
||||
bool update_dependencies;
|
||||
|
||||
SelfList<Instance> update_item;
|
||||
|
||||
AABB *custom_aabb; // <Zylann> would using aabb directly with a bool be better?
|
||||
float extra_margin;
|
||||
ObjectID object_id;
|
||||
|
||||
float lod_begin;
|
||||
float lod_end;
|
||||
float lod_begin_hysteresis;
|
||||
float lod_end_hysteresis;
|
||||
RID lod_instance;
|
||||
|
||||
uint64_t last_render_pass;
|
||||
uint64_t last_frame_pass;
|
||||
|
||||
uint64_t version; // changes to this, and changes to base increase version
|
||||
|
||||
InstanceBaseData *base_data;
|
||||
|
||||
virtual void dependency_deleted(RID p_dependency) {
|
||||
if (p_dependency == base) {
|
||||
singleton->instance_set_base(self, RID());
|
||||
} else if (p_dependency == skeleton) {
|
||||
singleton->instance_attach_skeleton(self, RID());
|
||||
} else {
|
||||
singleton->_instance_queue_update(this, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void dependency_changed(bool p_aabb, bool p_dependencies) {
|
||||
singleton->_instance_queue_update(this, p_aabb, p_dependencies);
|
||||
}
|
||||
|
||||
Instance() :
|
||||
scenario_item(this),
|
||||
update_item(this) {
|
||||
|
||||
octree_id = 0;
|
||||
scenario = NULL;
|
||||
|
||||
update_aabb = false;
|
||||
update_dependencies = false;
|
||||
|
||||
extra_margin = 0;
|
||||
|
||||
visible = true;
|
||||
|
||||
lod_begin = 0;
|
||||
lod_end = 0;
|
||||
lod_begin_hysteresis = 0;
|
||||
lod_end_hysteresis = 0;
|
||||
|
||||
last_render_pass = 0;
|
||||
last_frame_pass = 0;
|
||||
version = 1;
|
||||
base_data = NULL;
|
||||
|
||||
custom_aabb = NULL;
|
||||
}
|
||||
|
||||
~Instance() {
|
||||
|
||||
if (base_data)
|
||||
memdelete(base_data);
|
||||
if (custom_aabb)
|
||||
memdelete(custom_aabb);
|
||||
}
|
||||
};
|
||||
|
||||
SelfList<Instance>::List _instance_update_list;
|
||||
void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
|
||||
|
||||
struct InstanceGeometryData : public InstanceBaseData {
|
||||
|
||||
List<Instance *> lighting;
|
||||
bool lighting_dirty;
|
||||
bool can_cast_shadows;
|
||||
bool material_is_animated;
|
||||
|
||||
List<Instance *> reflection_probes;
|
||||
bool reflection_dirty;
|
||||
|
||||
List<Instance *> gi_probes;
|
||||
bool gi_probes_dirty;
|
||||
|
||||
List<Instance *> lightmap_captures;
|
||||
|
||||
InstanceGeometryData() {
|
||||
|
||||
lighting_dirty = false;
|
||||
reflection_dirty = true;
|
||||
can_cast_shadows = true;
|
||||
material_is_animated = true;
|
||||
gi_probes_dirty = true;
|
||||
}
|
||||
};
|
||||
|
||||
struct InstanceReflectionProbeData : public InstanceBaseData {
|
||||
|
||||
Instance *owner;
|
||||
|
||||
struct PairInfo {
|
||||
List<Instance *>::Element *L; //reflection iterator in geometry
|
||||
Instance *geometry;
|
||||
};
|
||||
List<PairInfo> geometries;
|
||||
|
||||
RID instance;
|
||||
bool reflection_dirty;
|
||||
SelfList<InstanceReflectionProbeData> update_list;
|
||||
|
||||
int render_step;
|
||||
|
||||
InstanceReflectionProbeData() :
|
||||
update_list(this) {
|
||||
|
||||
reflection_dirty = true;
|
||||
render_step = -1;
|
||||
}
|
||||
};
|
||||
|
||||
SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
|
||||
|
||||
struct InstanceLightData : public InstanceBaseData {
|
||||
|
||||
struct PairInfo {
|
||||
List<Instance *>::Element *L; //light iterator in geometry
|
||||
Instance *geometry;
|
||||
};
|
||||
|
||||
RID instance;
|
||||
uint64_t last_version;
|
||||
List<Instance *>::Element *D; // directional light in scenario
|
||||
|
||||
bool shadow_dirty;
|
||||
|
||||
List<PairInfo> geometries;
|
||||
|
||||
Instance *baked_light;
|
||||
|
||||
InstanceLightData() {
|
||||
|
||||
shadow_dirty = true;
|
||||
D = NULL;
|
||||
last_version = 0;
|
||||
baked_light = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
struct InstanceGIProbeData : public InstanceBaseData {
|
||||
|
||||
Instance *owner;
|
||||
|
||||
struct PairInfo {
|
||||
List<Instance *>::Element *L; //gi probe iterator in geometry
|
||||
Instance *geometry;
|
||||
};
|
||||
|
||||
List<PairInfo> geometries;
|
||||
List<PairInfo> dynamic_geometries;
|
||||
|
||||
Set<Instance *> lights;
|
||||
|
||||
struct LightCache {
|
||||
|
||||
RS::LightType type;
|
||||
Transform transform;
|
||||
Color color;
|
||||
float energy;
|
||||
float bake_energy;
|
||||
float radius;
|
||||
float attenuation;
|
||||
float spot_angle;
|
||||
float spot_attenuation;
|
||||
bool has_shadow;
|
||||
};
|
||||
|
||||
Vector<LightCache> light_cache;
|
||||
Vector<RID> light_instances;
|
||||
|
||||
RID probe_instance;
|
||||
|
||||
bool invalid;
|
||||
uint32_t base_version;
|
||||
|
||||
SelfList<InstanceGIProbeData> update_element;
|
||||
|
||||
InstanceGIProbeData() :
|
||||
update_element(this) {
|
||||
invalid = true;
|
||||
base_version = 0;
|
||||
}
|
||||
};
|
||||
|
||||
SelfList<InstanceGIProbeData>::List gi_probe_update_list;
|
||||
|
||||
struct InstanceLightmapCaptureData : public InstanceBaseData {
|
||||
|
||||
struct PairInfo {
|
||||
List<Instance *>::Element *L; //iterator in geometry
|
||||
Instance *geometry;
|
||||
};
|
||||
List<PairInfo> geometries;
|
||||
|
||||
Set<Instance *> users;
|
||||
|
||||
InstanceLightmapCaptureData() {
|
||||
}
|
||||
};
|
||||
|
||||
int instance_cull_count;
|
||||
Instance *instance_cull_result[MAX_INSTANCE_CULL];
|
||||
Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps
|
||||
Instance *light_cull_result[MAX_LIGHTS_CULLED];
|
||||
RID light_instance_cull_result[MAX_LIGHTS_CULLED];
|
||||
int light_cull_count;
|
||||
int directional_light_count;
|
||||
RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED];
|
||||
int reflection_probe_cull_count;
|
||||
RID gi_probe_instance_cull_result[MAX_GI_PROBES_CULLED];
|
||||
int gi_probe_cull_count;
|
||||
|
||||
RID_PtrOwner<Instance> instance_owner;
|
||||
|
||||
virtual RID instance_create();
|
||||
|
||||
virtual void instance_set_base(RID p_instance, RID p_base);
|
||||
virtual void instance_set_scenario(RID p_instance, RID p_scenario);
|
||||
virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask);
|
||||
virtual void instance_set_transform(RID p_instance, const Transform &p_transform);
|
||||
virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id);
|
||||
virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight);
|
||||
virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material);
|
||||
virtual void instance_set_visible(RID p_instance, bool p_visible);
|
||||
virtual void instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap);
|
||||
|
||||
virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb);
|
||||
|
||||
virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton);
|
||||
virtual void instance_set_exterior(RID p_instance, bool p_enabled);
|
||||
|
||||
virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin);
|
||||
|
||||
// don't use these in a game!
|
||||
virtual Vector<ObjectID> instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const;
|
||||
virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const;
|
||||
virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const;
|
||||
|
||||
virtual void instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled);
|
||||
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting);
|
||||
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material);
|
||||
|
||||
virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin);
|
||||
virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance);
|
||||
|
||||
_FORCE_INLINE_ void _update_instance(Instance *p_instance);
|
||||
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
|
||||
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
|
||||
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
|
||||
|
||||
_FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario);
|
||||
|
||||
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
|
||||
void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true);
|
||||
void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
|
||||
void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
|
||||
|
||||
void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
|
||||
void render_camera(RID p_render_buffers, Ref<ARVRInterface> &p_interface, ARVRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
|
||||
void update_dirty_instances();
|
||||
|
||||
void render_probes();
|
||||
|
||||
bool free(RID p_rid);
|
||||
|
||||
RenderingServerScene();
|
||||
virtual ~RenderingServerScene();
|
||||
};
|
||||
|
||||
#endif // VISUALSERVERSCENE_H
|
||||
780
servers/rendering/rendering_server_viewport.cpp
Normal file
780
servers/rendering/rendering_server_viewport.cpp
Normal file
|
|
@ -0,0 +1,780 @@
|
|||
/*************************************************************************/
|
||||
/* rendering_server_viewport.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "rendering_server_viewport.h"
|
||||
|
||||
#include "core/project_settings.h"
|
||||
#include "rendering_server_canvas.h"
|
||||
#include "rendering_server_globals.h"
|
||||
#include "rendering_server_scene.h"
|
||||
|
||||
static Transform2D _canvas_get_transform(RenderingServerViewport::Viewport *p_viewport, RenderingServerCanvas::Canvas *p_canvas, RenderingServerViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) {
|
||||
|
||||
Transform2D xf = p_viewport->global_transform;
|
||||
|
||||
float scale = 1.0;
|
||||
if (p_viewport->canvas_map.has(p_canvas->parent)) {
|
||||
xf = xf * p_viewport->canvas_map[p_canvas->parent].transform;
|
||||
scale = p_canvas->parent_scale;
|
||||
}
|
||||
|
||||
xf = xf * p_canvas_data->transform;
|
||||
|
||||
if (scale != 1.0 && !RSG::canvas->disable_scale) {
|
||||
Vector2 pivot = p_vp_size * 0.5;
|
||||
Transform2D xfpivot;
|
||||
xfpivot.set_origin(pivot);
|
||||
Transform2D xfscale;
|
||||
xfscale.scale(Vector2(scale, scale));
|
||||
|
||||
xf = xfpivot.affine_inverse() * xf;
|
||||
xf = xfscale * xf;
|
||||
xf = xfpivot * xf;
|
||||
}
|
||||
|
||||
return xf;
|
||||
}
|
||||
|
||||
void RenderingServerViewport::_draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye) {
|
||||
|
||||
RENDER_TIMESTAMP(">Begin Rendering 3D Scene");
|
||||
|
||||
Ref<ARVRInterface> arvr_interface;
|
||||
if (ARVRServer::get_singleton() != NULL) {
|
||||
arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
|
||||
}
|
||||
|
||||
if (p_viewport->use_arvr && arvr_interface.is_valid()) {
|
||||
RSG::scene->render_camera(p_viewport->render_buffers, arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
||||
} else {
|
||||
RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas);
|
||||
}
|
||||
RENDER_TIMESTAMP("<End Rendering 3D Scene");
|
||||
}
|
||||
|
||||
void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye) {
|
||||
|
||||
/* Camera should always be BEFORE any other 3D */
|
||||
|
||||
bool scenario_draw_canvas_bg = false; //draw canvas, or some layer of it, as BG for 3D instead of in front
|
||||
int scenario_canvas_max_layer = 0;
|
||||
|
||||
Color bgcolor = RSG::storage->get_default_clear_color();
|
||||
|
||||
if (!p_viewport->hide_canvas && !p_viewport->disable_environment && RSG::scene->scenario_owner.owns(p_viewport->scenario)) {
|
||||
|
||||
RenderingServerScene::Scenario *scenario = RSG::scene->scenario_owner.getornull(p_viewport->scenario);
|
||||
ERR_FAIL_COND(!scenario);
|
||||
if (RSG::scene_render->is_environment(scenario->environment)) {
|
||||
scenario_draw_canvas_bg = RSG::scene_render->environment_get_background(scenario->environment) == RS::ENV_BG_CANVAS;
|
||||
|
||||
scenario_canvas_max_layer = RSG::scene_render->environment_get_canvas_max_layer(scenario->environment);
|
||||
}
|
||||
}
|
||||
|
||||
bool can_draw_3d = RSG::scene->camera_owner.owns(p_viewport->camera);
|
||||
|
||||
if (p_viewport->clear_mode != RS::VIEWPORT_CLEAR_NEVER) {
|
||||
if (p_viewport->transparent_bg) {
|
||||
bgcolor = Color(0, 0, 0, 0);
|
||||
}
|
||||
if (p_viewport->clear_mode == RS::VIEWPORT_CLEAR_ONLY_NEXT_FRAME) {
|
||||
p_viewport->clear_mode = RS::VIEWPORT_CLEAR_NEVER;
|
||||
}
|
||||
}
|
||||
|
||||
if ((scenario_draw_canvas_bg || can_draw_3d) && !p_viewport->render_buffers.is_valid()) {
|
||||
//wants to draw 3D but there is no render buffer, create
|
||||
p_viewport->render_buffers = RSG::scene_render->render_buffers_create();
|
||||
RSG::scene_render->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa);
|
||||
}
|
||||
|
||||
RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor);
|
||||
|
||||
if (!scenario_draw_canvas_bg && can_draw_3d) {
|
||||
_draw_3d(p_viewport, p_eye);
|
||||
}
|
||||
|
||||
if (!p_viewport->hide_canvas) {
|
||||
int i = 0;
|
||||
|
||||
Map<Viewport::CanvasKey, Viewport::CanvasData *> canvas_map;
|
||||
|
||||
Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y);
|
||||
RasterizerCanvas::Light *lights = NULL;
|
||||
RasterizerCanvas::Light *lights_with_shadow = NULL;
|
||||
RasterizerCanvas::Light *lights_with_mask = NULL;
|
||||
Rect2 shadow_rect;
|
||||
|
||||
int light_count = 0;
|
||||
|
||||
RENDER_TIMESTAMP("Cull Canvas Lights");
|
||||
for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
|
||||
|
||||
RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas);
|
||||
|
||||
Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
|
||||
|
||||
//find lights in canvas
|
||||
|
||||
for (Set<RasterizerCanvas::Light *>::Element *F = canvas->lights.front(); F; F = F->next()) {
|
||||
|
||||
RasterizerCanvas::Light *cl = F->get();
|
||||
if (cl->enabled && cl->texture.is_valid()) {
|
||||
//not super efficient..
|
||||
Size2 tsize = RSG::storage->texture_size_with_proxy(cl->texture);
|
||||
tsize *= cl->scale;
|
||||
|
||||
Vector2 offset = tsize / 2.0;
|
||||
cl->rect_cache = Rect2(-offset + cl->texture_offset, tsize);
|
||||
cl->xform_cache = xf * cl->xform;
|
||||
|
||||
if (clip_rect.intersects_transformed(cl->xform_cache, cl->rect_cache)) {
|
||||
|
||||
cl->filter_next_ptr = lights;
|
||||
lights = cl;
|
||||
// cl->texture_cache = NULL;
|
||||
Transform2D scale;
|
||||
scale.scale(cl->rect_cache.size);
|
||||
scale.elements[2] = cl->rect_cache.position;
|
||||
cl->light_shader_xform = cl->xform * scale;
|
||||
//cl->light_shader_pos = cl->xform_cache[2];
|
||||
if (cl->use_shadow) {
|
||||
|
||||
cl->shadows_next_ptr = lights_with_shadow;
|
||||
if (lights_with_shadow == NULL) {
|
||||
shadow_rect = cl->xform_cache.xform(cl->rect_cache);
|
||||
} else {
|
||||
shadow_rect = shadow_rect.merge(cl->xform_cache.xform(cl->rect_cache));
|
||||
}
|
||||
lights_with_shadow = cl;
|
||||
cl->radius_cache = cl->rect_cache.size.length();
|
||||
}
|
||||
if (cl->mode == RS::CANVAS_LIGHT_MODE_MASK) {
|
||||
cl->mask_next_ptr = lights_with_mask;
|
||||
lights_with_mask = cl;
|
||||
}
|
||||
|
||||
light_count++;
|
||||
}
|
||||
|
||||
//guess this is not needed, but keeping because it may be
|
||||
//RSG::canvas_render->light_internal_update(cl->light_internal, cl);
|
||||
}
|
||||
}
|
||||
|
||||
canvas_map[Viewport::CanvasKey(E->key(), E->get().layer, E->get().sublayer)] = &E->get();
|
||||
}
|
||||
|
||||
if (lights_with_shadow) {
|
||||
//update shadows if any
|
||||
|
||||
RasterizerCanvas::LightOccluderInstance *occluders = NULL;
|
||||
|
||||
RENDER_TIMESTAMP(">Render 2D Shadows");
|
||||
RENDER_TIMESTAMP("Cull Occluders");
|
||||
|
||||
//make list of occluders
|
||||
for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) {
|
||||
|
||||
RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas);
|
||||
Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size);
|
||||
|
||||
for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) {
|
||||
|
||||
if (!F->get()->enabled)
|
||||
continue;
|
||||
F->get()->xform_cache = xf * F->get()->xform;
|
||||
if (shadow_rect.intersects_transformed(F->get()->xform_cache, F->get()->aabb_cache)) {
|
||||
|
||||
F->get()->next = occluders;
|
||||
occluders = F->get();
|
||||
}
|
||||
}
|
||||
}
|
||||
//update the light shadowmaps with them
|
||||
|
||||
RasterizerCanvas::Light *light = lights_with_shadow;
|
||||
while (light) {
|
||||
|
||||
RENDER_TIMESTAMP("Render Shadow");
|
||||
|
||||
RSG::canvas_render->light_update_shadow(light->light_internal, light->xform_cache.affine_inverse(), light->item_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders);
|
||||
light = light->shadows_next_ptr;
|
||||
}
|
||||
|
||||
//RSG::canvas_render->reset_canvas();
|
||||
RENDER_TIMESTAMP("<End rendering 2D Shadows");
|
||||
}
|
||||
|
||||
if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) {
|
||||
if (!can_draw_3d) {
|
||||
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
|
||||
} else {
|
||||
_draw_3d(p_viewport, p_eye);
|
||||
}
|
||||
scenario_draw_canvas_bg = false;
|
||||
}
|
||||
|
||||
for (Map<Viewport::CanvasKey, Viewport::CanvasData *>::Element *E = canvas_map.front(); E; E = E->next()) {
|
||||
|
||||
RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get()->canvas);
|
||||
|
||||
Transform2D xform = _canvas_get_transform(p_viewport, canvas, E->get(), clip_rect.size);
|
||||
|
||||
RasterizerCanvas::Light *canvas_lights = NULL;
|
||||
|
||||
RasterizerCanvas::Light *ptr = lights;
|
||||
while (ptr) {
|
||||
if (E->get()->layer >= ptr->layer_min && E->get()->layer <= ptr->layer_max) {
|
||||
ptr->next_ptr = canvas_lights;
|
||||
canvas_lights = ptr;
|
||||
}
|
||||
ptr = ptr->filter_next_ptr;
|
||||
}
|
||||
|
||||
RSG::canvas->render_canvas(p_viewport->render_target, canvas, xform, canvas_lights, lights_with_mask, clip_rect);
|
||||
i++;
|
||||
|
||||
if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) {
|
||||
if (!can_draw_3d) {
|
||||
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
|
||||
} else {
|
||||
_draw_3d(p_viewport, p_eye);
|
||||
}
|
||||
|
||||
scenario_draw_canvas_bg = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (scenario_draw_canvas_bg) {
|
||||
if (!can_draw_3d) {
|
||||
RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas);
|
||||
} else {
|
||||
_draw_3d(p_viewport, p_eye);
|
||||
}
|
||||
}
|
||||
|
||||
//RSG::canvas_render->canvas_debug_viewport_shadows(lights_with_shadow);
|
||||
}
|
||||
|
||||
if (RSG::storage->render_target_is_clear_requested(p_viewport->render_target)) {
|
||||
//was never cleared in the end, force clear it
|
||||
RSG::storage->render_target_do_clear_request(p_viewport->render_target);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingServerViewport::draw_viewports() {
|
||||
|
||||
#if 0
|
||||
// get our arvr interface in case we need it
|
||||
Ref<ARVRInterface> arvr_interface;
|
||||
|
||||
if (ARVRServer::get_singleton() != NULL) {
|
||||
arvr_interface = ARVRServer::get_singleton()->get_primary_interface();
|
||||
|
||||
// process all our active interfaces
|
||||
ARVRServer::get_singleton()->_process();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
set_default_clear_color(GLOBAL_GET("rendering/environment/default_clear_color"));
|
||||
}
|
||||
|
||||
//sort viewports
|
||||
active_viewports.sort_custom<ViewportSort>();
|
||||
|
||||
Map<DisplayServer::WindowID, Vector<Rasterizer::BlitToScreen>> blit_to_screen_list;
|
||||
//draw viewports
|
||||
RENDER_TIMESTAMP(">Render Viewports");
|
||||
|
||||
//determine what is visible
|
||||
draw_viewports_pass++;
|
||||
|
||||
for (int i = active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order
|
||||
|
||||
Viewport *vp = active_viewports[i];
|
||||
|
||||
if (vp->update_mode == RS::VIEWPORT_UPDATE_DISABLED)
|
||||
continue;
|
||||
|
||||
if (!vp->render_target.is_valid()) {
|
||||
continue;
|
||||
}
|
||||
//ERR_CONTINUE(!vp->render_target.is_valid());
|
||||
|
||||
bool visible = vp->viewport_to_screen_rect != Rect2();
|
||||
|
||||
if (vp->update_mode == RS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == RS::VIEWPORT_UPDATE_ONCE) {
|
||||
visible = true;
|
||||
}
|
||||
|
||||
if (vp->update_mode == RS::VIEWPORT_UPDATE_WHEN_VISIBLE && RSG::storage->render_target_was_used(vp->render_target)) {
|
||||
visible = true;
|
||||
}
|
||||
|
||||
if (vp->update_mode == RS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE) {
|
||||
Viewport *parent = viewport_owner.getornull(vp->parent);
|
||||
if (parent && parent->last_pass == draw_viewports_pass) {
|
||||
visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
visible = visible && vp->size.x > 1 && vp->size.y > 1;
|
||||
|
||||
if (visible) {
|
||||
vp->last_pass = draw_viewports_pass;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < active_viewports.size(); i++) {
|
||||
|
||||
Viewport *vp = active_viewports[i];
|
||||
|
||||
if (vp->last_pass != draw_viewports_pass) {
|
||||
continue; //should not draw
|
||||
}
|
||||
|
||||
RENDER_TIMESTAMP(">Rendering Viewport " + itos(i));
|
||||
|
||||
RSG::storage->render_target_set_as_unused(vp->render_target);
|
||||
#if 0
|
||||
if (vp->use_arvr && arvr_interface.is_valid()) {
|
||||
// override our size, make sure it matches our required size
|
||||
vp->size = arvr_interface->get_render_targetsize();
|
||||
RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y);
|
||||
|
||||
// render mono or left eye first
|
||||
ARVRInterface::Eyes leftOrMono = arvr_interface->is_stereo() ? ARVRInterface::EYE_LEFT : ARVRInterface::EYE_MONO;
|
||||
|
||||
// check for an external texture destination for our left eye/mono
|
||||
RSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(leftOrMono));
|
||||
|
||||
// set our render target as current
|
||||
RSG::rasterizer->set_current_render_target(vp->render_target);
|
||||
|
||||
// and draw left eye/mono
|
||||
_draw_viewport(vp, leftOrMono);
|
||||
arvr_interface->commit_for_eye(leftOrMono, vp->render_target, vp->viewport_to_screen_rect);
|
||||
|
||||
// render right eye
|
||||
if (leftOrMono == ARVRInterface::EYE_LEFT) {
|
||||
// check for an external texture destination for our right eye
|
||||
RSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(ARVRInterface::EYE_RIGHT));
|
||||
|
||||
// commit for eye may have changed the render target
|
||||
RSG::rasterizer->set_current_render_target(vp->render_target);
|
||||
|
||||
_draw_viewport(vp, ARVRInterface::EYE_RIGHT);
|
||||
arvr_interface->commit_for_eye(ARVRInterface::EYE_RIGHT, vp->render_target, vp->viewport_to_screen_rect);
|
||||
}
|
||||
|
||||
// and for our frame timing, mark when we've finished committing our eyes
|
||||
ARVRServer::get_singleton()->_mark_commit();
|
||||
} else {
|
||||
#endif
|
||||
{
|
||||
RSG::storage->render_target_set_external_texture(vp->render_target, 0);
|
||||
|
||||
RSG::scene_render->set_debug_draw_mode(vp->debug_draw);
|
||||
RSG::storage->render_info_begin_capture();
|
||||
|
||||
// render standard mono camera
|
||||
_draw_viewport(vp);
|
||||
|
||||
RSG::storage->render_info_end_capture();
|
||||
vp->render_info[RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_OBJECTS_IN_FRAME);
|
||||
vp->render_info[RS::VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_VERTICES_IN_FRAME);
|
||||
vp->render_info[RS::VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_MATERIAL_CHANGES_IN_FRAME);
|
||||
vp->render_info[RS::VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_SHADER_CHANGES_IN_FRAME);
|
||||
vp->render_info[RS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_SURFACE_CHANGES_IN_FRAME);
|
||||
vp->render_info[RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_DRAW_CALLS_IN_FRAME);
|
||||
|
||||
if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && (!vp->viewport_render_direct_to_screen || !RSG::rasterizer->is_low_end())) {
|
||||
//copy to screen if set as such
|
||||
Rasterizer::BlitToScreen blit;
|
||||
blit.render_target = vp->render_target;
|
||||
if (vp->viewport_to_screen_rect != Rect2()) {
|
||||
blit.rect = vp->viewport_to_screen_rect;
|
||||
} else {
|
||||
blit.rect.position = Vector2();
|
||||
blit.rect.size = vp->size;
|
||||
}
|
||||
|
||||
if (!blit_to_screen_list.has(vp->viewport_to_screen)) {
|
||||
blit_to_screen_list[vp->viewport_to_screen] = Vector<Rasterizer::BlitToScreen>();
|
||||
}
|
||||
|
||||
blit_to_screen_list[vp->viewport_to_screen].push_back(blit);
|
||||
}
|
||||
}
|
||||
|
||||
if (vp->update_mode == RS::VIEWPORT_UPDATE_ONCE) {
|
||||
vp->update_mode = RS::VIEWPORT_UPDATE_DISABLED;
|
||||
}
|
||||
|
||||
RENDER_TIMESTAMP("<Rendering Viewport " + itos(i));
|
||||
}
|
||||
RSG::scene_render->set_debug_draw_mode(RS::VIEWPORT_DEBUG_DRAW_DISABLED);
|
||||
|
||||
RENDER_TIMESTAMP("<Render Viewports");
|
||||
//this needs to be called to make screen swapping more efficient
|
||||
RSG::rasterizer->prepare_for_blitting_render_targets();
|
||||
|
||||
for (Map<int, Vector<Rasterizer::BlitToScreen>>::Element *E = blit_to_screen_list.front(); E; E = E->next()) {
|
||||
RSG::rasterizer->blit_render_targets_to_screen(E->key(), E->get().ptr(), E->get().size());
|
||||
}
|
||||
}
|
||||
|
||||
RID RenderingServerViewport::viewport_create() {
|
||||
|
||||
Viewport *viewport = memnew(Viewport);
|
||||
|
||||
RID rid = viewport_owner.make_rid(viewport);
|
||||
|
||||
viewport->self = rid;
|
||||
viewport->hide_scenario = false;
|
||||
viewport->hide_canvas = false;
|
||||
viewport->render_target = RSG::storage->render_target_create();
|
||||
viewport->shadow_atlas = RSG::scene_render->shadow_atlas_create();
|
||||
viewport->viewport_render_direct_to_screen = false;
|
||||
|
||||
return rid;
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_use_arvr(RID p_viewport, bool p_use_arvr) {
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->use_arvr = p_use_arvr;
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) {
|
||||
|
||||
ERR_FAIL_COND(p_width < 0 && p_height < 0);
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->size = Size2(p_width, p_height);
|
||||
RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height);
|
||||
if (viewport->render_buffers.is_valid()) {
|
||||
if (p_width == 0 || p_height == 0) {
|
||||
RSG::scene_render->free(viewport->render_buffers);
|
||||
viewport->render_buffers = RID();
|
||||
} else {
|
||||
RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_active(RID p_viewport, bool p_active) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
if (p_active) {
|
||||
ERR_FAIL_COND(active_viewports.find(viewport) != -1); //already active
|
||||
active_viewports.push_back(viewport);
|
||||
} else {
|
||||
active_viewports.erase(viewport);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->parent = p_parent_viewport;
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_clear_mode(RID p_viewport, RS::ViewportClearMode p_clear_mode) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->clear_mode = p_clear_mode;
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect, DisplayServer::WindowID p_screen) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
if (p_screen != DisplayServer::INVALID_WINDOW_ID) {
|
||||
// If using GLES2 we can optimize this operation by rendering directly to system_fbo
|
||||
// instead of rendering to fbo and copying to system_fbo after
|
||||
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
|
||||
|
||||
RSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y);
|
||||
RSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
|
||||
}
|
||||
|
||||
viewport->viewport_to_screen_rect = p_rect;
|
||||
viewport->viewport_to_screen = p_screen;
|
||||
} else {
|
||||
|
||||
// if render_direct_to_screen was used, reset size and position
|
||||
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
|
||||
|
||||
RSG::storage->render_target_set_position(viewport->render_target, 0, 0);
|
||||
RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y);
|
||||
}
|
||||
|
||||
viewport->viewport_to_screen_rect = Rect2();
|
||||
viewport->viewport_to_screen = DisplayServer::INVALID_WINDOW_ID;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) {
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
if (p_enable == viewport->viewport_render_direct_to_screen)
|
||||
return;
|
||||
|
||||
// if disabled, reset render_target size and position
|
||||
if (!p_enable) {
|
||||
|
||||
RSG::storage->render_target_set_position(viewport->render_target, 0, 0);
|
||||
RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y);
|
||||
}
|
||||
|
||||
RSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable);
|
||||
viewport->viewport_render_direct_to_screen = p_enable;
|
||||
|
||||
// if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation
|
||||
if (RSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) {
|
||||
|
||||
RSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y);
|
||||
RSG::storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->update_mode = p_mode;
|
||||
}
|
||||
|
||||
RID RenderingServerViewport::viewport_get_texture(RID p_viewport) const {
|
||||
|
||||
const Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND_V(!viewport, RID());
|
||||
|
||||
return RSG::storage->render_target_get_texture(viewport->render_target);
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_hide_scenario(RID p_viewport, bool p_hide) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->hide_scenario = p_hide;
|
||||
}
|
||||
void RenderingServerViewport::viewport_set_hide_canvas(RID p_viewport, bool p_hide) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->hide_canvas = p_hide;
|
||||
}
|
||||
void RenderingServerViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->disable_environment = p_disable;
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_attach_camera(RID p_viewport, RID p_camera) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->camera = p_camera;
|
||||
}
|
||||
void RenderingServerViewport::viewport_set_scenario(RID p_viewport, RID p_scenario) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->scenario = p_scenario;
|
||||
}
|
||||
void RenderingServerViewport::viewport_attach_canvas(RID p_viewport, RID p_canvas) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
ERR_FAIL_COND(viewport->canvas_map.has(p_canvas));
|
||||
RenderingServerCanvas::Canvas *canvas = RSG::canvas->canvas_owner.getornull(p_canvas);
|
||||
ERR_FAIL_COND(!canvas);
|
||||
|
||||
canvas->viewports.insert(p_viewport);
|
||||
viewport->canvas_map[p_canvas] = Viewport::CanvasData();
|
||||
viewport->canvas_map[p_canvas].layer = 0;
|
||||
viewport->canvas_map[p_canvas].sublayer = 0;
|
||||
viewport->canvas_map[p_canvas].canvas = canvas;
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_remove_canvas(RID p_viewport, RID p_canvas) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
RenderingServerCanvas::Canvas *canvas = RSG::canvas->canvas_owner.getornull(p_canvas);
|
||||
ERR_FAIL_COND(!canvas);
|
||||
|
||||
viewport->canvas_map.erase(p_canvas);
|
||||
canvas->viewports.erase(p_viewport);
|
||||
}
|
||||
void RenderingServerViewport::viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas));
|
||||
viewport->canvas_map[p_canvas].transform = p_offset;
|
||||
}
|
||||
void RenderingServerViewport::viewport_set_transparent_background(RID p_viewport, bool p_enabled) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
RSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_TRANSPARENT, p_enabled);
|
||||
viewport->transparent_bg = p_enabled;
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->global_transform = p_transform;
|
||||
}
|
||||
void RenderingServerViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas));
|
||||
viewport->canvas_map[p_canvas].layer = p_layer;
|
||||
viewport->canvas_map[p_canvas].sublayer = p_sublayer;
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->shadow_atlas_size = p_size;
|
||||
|
||||
RSG::scene_render->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size);
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
RSG::scene_render->shadow_atlas_set_quadrant_subdivision(viewport->shadow_atlas, p_quadrant, p_subdiv);
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
if (viewport->msaa == p_msaa) {
|
||||
return;
|
||||
}
|
||||
viewport->msaa = p_msaa;
|
||||
if (viewport->render_buffers.is_valid()) {
|
||||
RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa);
|
||||
}
|
||||
}
|
||||
|
||||
int RenderingServerViewport::viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info) {
|
||||
|
||||
ERR_FAIL_INDEX_V(p_info, RS::VIEWPORT_RENDER_INFO_MAX, -1);
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
if (!viewport)
|
||||
return 0; //there should be a lock here..
|
||||
|
||||
return viewport->render_info[p_info];
|
||||
}
|
||||
|
||||
void RenderingServerViewport::viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_viewport);
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->debug_draw = p_draw;
|
||||
}
|
||||
|
||||
bool RenderingServerViewport::free(RID p_rid) {
|
||||
|
||||
if (viewport_owner.owns(p_rid)) {
|
||||
|
||||
Viewport *viewport = viewport_owner.getornull(p_rid);
|
||||
|
||||
RSG::storage->free(viewport->render_target);
|
||||
RSG::scene_render->free(viewport->shadow_atlas);
|
||||
if (viewport->render_buffers.is_valid()) {
|
||||
RSG::scene_render->free(viewport->render_buffers);
|
||||
}
|
||||
|
||||
while (viewport->canvas_map.front()) {
|
||||
viewport_remove_canvas(p_rid, viewport->canvas_map.front()->key());
|
||||
}
|
||||
|
||||
viewport_set_scenario(p_rid, RID());
|
||||
active_viewports.erase(viewport);
|
||||
|
||||
viewport_owner.free(p_rid);
|
||||
memdelete(viewport);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void RenderingServerViewport::set_default_clear_color(const Color &p_color) {
|
||||
RSG::storage->set_default_clear_color(p_color);
|
||||
}
|
||||
|
||||
RenderingServerViewport::RenderingServerViewport() {
|
||||
}
|
||||
208
servers/rendering/rendering_server_viewport.h
Normal file
208
servers/rendering/rendering_server_viewport.h
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/*************************************************************************/
|
||||
/* rendering_server_viewport.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef VISUALSERVERVIEWPORT_H
|
||||
#define VISUALSERVERVIEWPORT_H
|
||||
|
||||
#include "core/rid_owner.h"
|
||||
#include "core/self_list.h"
|
||||
#include "rasterizer.h"
|
||||
#include "servers/arvr/arvr_interface.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
class RenderingServerViewport {
|
||||
public:
|
||||
struct CanvasBase {
|
||||
};
|
||||
|
||||
struct Viewport {
|
||||
|
||||
RID self;
|
||||
RID parent;
|
||||
|
||||
bool use_arvr; /* use arvr interface to override camera positioning and projection matrices and control output */
|
||||
|
||||
Size2i size;
|
||||
RID camera;
|
||||
RID scenario;
|
||||
|
||||
RS::ViewportUpdateMode update_mode;
|
||||
RID render_target;
|
||||
RID render_target_texture;
|
||||
RID render_buffers;
|
||||
|
||||
RS::ViewportMSAA msaa;
|
||||
|
||||
DisplayServer::WindowID viewport_to_screen;
|
||||
Rect2 viewport_to_screen_rect;
|
||||
bool viewport_render_direct_to_screen;
|
||||
|
||||
bool hide_scenario;
|
||||
bool hide_canvas;
|
||||
bool disable_environment;
|
||||
bool disable_3d_by_usage;
|
||||
bool keep_3d_linear;
|
||||
|
||||
RID shadow_atlas;
|
||||
int shadow_atlas_size;
|
||||
|
||||
uint64_t last_pass = 0;
|
||||
|
||||
int render_info[RS::VIEWPORT_RENDER_INFO_MAX];
|
||||
RS::ViewportDebugDraw debug_draw;
|
||||
|
||||
RS::ViewportClearMode clear_mode;
|
||||
|
||||
bool transparent_bg;
|
||||
|
||||
struct CanvasKey {
|
||||
|
||||
int64_t stacking;
|
||||
RID canvas;
|
||||
bool operator<(const CanvasKey &p_canvas) const {
|
||||
if (stacking == p_canvas.stacking)
|
||||
return canvas < p_canvas.canvas;
|
||||
return stacking < p_canvas.stacking;
|
||||
}
|
||||
CanvasKey() {
|
||||
stacking = 0;
|
||||
}
|
||||
CanvasKey(const RID &p_canvas, int p_layer, int p_sublayer) {
|
||||
canvas = p_canvas;
|
||||
int64_t sign = p_layer < 0 ? -1 : 1;
|
||||
stacking = sign * (((int64_t)ABS(p_layer)) << 32) + p_sublayer;
|
||||
}
|
||||
int get_layer() const { return stacking >> 32; }
|
||||
};
|
||||
|
||||
struct CanvasData {
|
||||
|
||||
CanvasBase *canvas;
|
||||
Transform2D transform;
|
||||
int layer;
|
||||
int sublayer;
|
||||
};
|
||||
|
||||
Transform2D global_transform;
|
||||
|
||||
Map<RID, CanvasData> canvas_map;
|
||||
|
||||
Viewport() {
|
||||
update_mode = RS::VIEWPORT_UPDATE_WHEN_VISIBLE;
|
||||
clear_mode = RS::VIEWPORT_CLEAR_ALWAYS;
|
||||
transparent_bg = false;
|
||||
disable_environment = false;
|
||||
viewport_to_screen = DisplayServer::INVALID_WINDOW_ID;
|
||||
shadow_atlas_size = 0;
|
||||
keep_3d_linear = false;
|
||||
debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
|
||||
msaa = RS::VIEWPORT_MSAA_DISABLED;
|
||||
for (int i = 0; i < RS::VIEWPORT_RENDER_INFO_MAX; i++) {
|
||||
render_info[i] = 0;
|
||||
}
|
||||
use_arvr = false;
|
||||
}
|
||||
};
|
||||
|
||||
uint64_t draw_viewports_pass = 0;
|
||||
|
||||
mutable RID_PtrOwner<Viewport> viewport_owner;
|
||||
|
||||
struct ViewportSort {
|
||||
_FORCE_INLINE_ bool operator()(const Viewport *p_left, const Viewport *p_right) const {
|
||||
|
||||
bool left_to_screen = p_left->viewport_to_screen_rect.size != Size2();
|
||||
bool right_to_screen = p_right->viewport_to_screen_rect.size != Size2();
|
||||
|
||||
if (left_to_screen == right_to_screen) {
|
||||
|
||||
return p_right->parent == p_left->self;
|
||||
}
|
||||
return (right_to_screen ? 0 : 1) < (left_to_screen ? 0 : 1);
|
||||
}
|
||||
};
|
||||
|
||||
Vector<Viewport *> active_viewports;
|
||||
|
||||
private:
|
||||
void _draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye);
|
||||
void _draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye = ARVRInterface::EYE_MONO);
|
||||
|
||||
public:
|
||||
RID viewport_create();
|
||||
|
||||
void viewport_set_use_arvr(RID p_viewport, bool p_use_arvr);
|
||||
|
||||
void viewport_set_size(RID p_viewport, int p_width, int p_height);
|
||||
|
||||
void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID);
|
||||
void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable);
|
||||
|
||||
void viewport_set_active(RID p_viewport, bool p_active);
|
||||
void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport);
|
||||
void viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode);
|
||||
void viewport_set_vflip(RID p_viewport, bool p_enable);
|
||||
|
||||
void viewport_set_clear_mode(RID p_viewport, RS::ViewportClearMode p_clear_mode);
|
||||
|
||||
RID viewport_get_texture(RID p_viewport) const;
|
||||
|
||||
void viewport_set_hide_scenario(RID p_viewport, bool p_hide);
|
||||
void viewport_set_hide_canvas(RID p_viewport, bool p_hide);
|
||||
void viewport_set_disable_environment(RID p_viewport, bool p_disable);
|
||||
|
||||
void viewport_attach_camera(RID p_viewport, RID p_camera);
|
||||
void viewport_set_scenario(RID p_viewport, RID p_scenario);
|
||||
void viewport_attach_canvas(RID p_viewport, RID p_canvas);
|
||||
void viewport_remove_canvas(RID p_viewport, RID p_canvas);
|
||||
void viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset);
|
||||
void viewport_set_transparent_background(RID p_viewport, bool p_enabled);
|
||||
|
||||
void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform);
|
||||
void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer);
|
||||
|
||||
void viewport_set_shadow_atlas_size(RID p_viewport, int p_size);
|
||||
void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);
|
||||
|
||||
void viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa);
|
||||
|
||||
virtual int viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info);
|
||||
virtual void viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw);
|
||||
|
||||
void set_default_clear_color(const Color &p_color);
|
||||
void draw_viewports();
|
||||
|
||||
bool free(RID p_rid);
|
||||
|
||||
RenderingServerViewport();
|
||||
virtual ~RenderingServerViewport() {}
|
||||
};
|
||||
|
||||
#endif // VISUALSERVERVIEWPORT_H
|
||||
197
servers/rendering/rendering_server_wrap_mt.cpp
Normal file
197
servers/rendering/rendering_server_wrap_mt.cpp
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/*************************************************************************/
|
||||
/* rendering_server_wrap_mt.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "rendering_server_wrap_mt.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/project_settings.h"
|
||||
#include "servers/display_server.h"
|
||||
|
||||
void RenderingServerWrapMT::thread_exit() {
|
||||
|
||||
exit = true;
|
||||
}
|
||||
|
||||
void RenderingServerWrapMT::thread_draw(bool p_swap_buffers, double frame_step) {
|
||||
|
||||
if (!atomic_decrement(&draw_pending)) {
|
||||
|
||||
rendering_server->draw(p_swap_buffers, frame_step);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingServerWrapMT::thread_flush() {
|
||||
|
||||
atomic_decrement(&draw_pending);
|
||||
}
|
||||
|
||||
void RenderingServerWrapMT::_thread_callback(void *_instance) {
|
||||
|
||||
RenderingServerWrapMT *vsmt = reinterpret_cast<RenderingServerWrapMT *>(_instance);
|
||||
|
||||
vsmt->thread_loop();
|
||||
}
|
||||
|
||||
void RenderingServerWrapMT::thread_loop() {
|
||||
|
||||
server_thread = Thread::get_caller_id();
|
||||
|
||||
DisplayServer::get_singleton()->make_rendering_thread();
|
||||
|
||||
rendering_server->init();
|
||||
|
||||
exit = false;
|
||||
draw_thread_up = true;
|
||||
while (!exit) {
|
||||
// flush commands one by one, until exit is requested
|
||||
command_queue.wait_and_flush_one();
|
||||
}
|
||||
|
||||
command_queue.flush_all(); // flush all
|
||||
|
||||
rendering_server->finish();
|
||||
}
|
||||
|
||||
/* EVENT QUEUING */
|
||||
|
||||
void RenderingServerWrapMT::sync() {
|
||||
|
||||
if (create_thread) {
|
||||
|
||||
atomic_increment(&draw_pending);
|
||||
command_queue.push_and_sync(this, &RenderingServerWrapMT::thread_flush);
|
||||
} else {
|
||||
|
||||
command_queue.flush_all(); //flush all pending from other threads
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingServerWrapMT::draw(bool p_swap_buffers, double frame_step) {
|
||||
|
||||
if (create_thread) {
|
||||
|
||||
atomic_increment(&draw_pending);
|
||||
command_queue.push(this, &RenderingServerWrapMT::thread_draw, p_swap_buffers, frame_step);
|
||||
} else {
|
||||
|
||||
rendering_server->draw(p_swap_buffers, frame_step);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingServerWrapMT::init() {
|
||||
|
||||
if (create_thread) {
|
||||
|
||||
print_verbose("RenderingServerWrapMT: Creating render thread");
|
||||
DisplayServer::get_singleton()->release_rendering_thread();
|
||||
if (create_thread) {
|
||||
thread = Thread::create(_thread_callback, this);
|
||||
print_verbose("RenderingServerWrapMT: Starting render thread");
|
||||
}
|
||||
while (!draw_thread_up) {
|
||||
OS::get_singleton()->delay_usec(1000);
|
||||
}
|
||||
print_verbose("RenderingServerWrapMT: Finished render thread");
|
||||
} else {
|
||||
|
||||
rendering_server->init();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingServerWrapMT::finish() {
|
||||
|
||||
if (thread) {
|
||||
|
||||
command_queue.push(this, &RenderingServerWrapMT::thread_exit);
|
||||
Thread::wait_to_finish(thread);
|
||||
memdelete(thread);
|
||||
|
||||
thread = NULL;
|
||||
} else {
|
||||
rendering_server->finish();
|
||||
}
|
||||
|
||||
sky_free_cached_ids();
|
||||
shader_free_cached_ids();
|
||||
material_free_cached_ids();
|
||||
mesh_free_cached_ids();
|
||||
multimesh_free_cached_ids();
|
||||
immediate_free_cached_ids();
|
||||
skeleton_free_cached_ids();
|
||||
directional_light_free_cached_ids();
|
||||
omni_light_free_cached_ids();
|
||||
spot_light_free_cached_ids();
|
||||
reflection_probe_free_cached_ids();
|
||||
gi_probe_free_cached_ids();
|
||||
lightmap_capture_free_cached_ids();
|
||||
particles_free_cached_ids();
|
||||
camera_free_cached_ids();
|
||||
viewport_free_cached_ids();
|
||||
environment_free_cached_ids();
|
||||
camera_effects_free_cached_ids();
|
||||
scenario_free_cached_ids();
|
||||
instance_free_cached_ids();
|
||||
canvas_free_cached_ids();
|
||||
canvas_item_free_cached_ids();
|
||||
canvas_light_occluder_free_cached_ids();
|
||||
canvas_occluder_polygon_free_cached_ids();
|
||||
}
|
||||
|
||||
void RenderingServerWrapMT::set_use_vsync_callback(bool p_enable) {
|
||||
|
||||
singleton_mt->call_set_use_vsync(p_enable);
|
||||
}
|
||||
|
||||
RenderingServerWrapMT *RenderingServerWrapMT::singleton_mt = NULL;
|
||||
|
||||
RenderingServerWrapMT::RenderingServerWrapMT(RenderingServer *p_contained, bool p_create_thread) :
|
||||
command_queue(p_create_thread) {
|
||||
|
||||
singleton_mt = this;
|
||||
DisplayServer::switch_vsync_function = set_use_vsync_callback; //as this goes to another thread, make sure it goes properly
|
||||
|
||||
rendering_server = p_contained;
|
||||
create_thread = p_create_thread;
|
||||
thread = NULL;
|
||||
draw_pending = 0;
|
||||
draw_thread_up = false;
|
||||
pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc");
|
||||
|
||||
if (!p_create_thread) {
|
||||
server_thread = Thread::get_caller_id();
|
||||
} else {
|
||||
server_thread = 0;
|
||||
}
|
||||
}
|
||||
|
||||
RenderingServerWrapMT::~RenderingServerWrapMT() {
|
||||
|
||||
memdelete(rendering_server);
|
||||
//finish();
|
||||
}
|
||||
678
servers/rendering/rendering_server_wrap_mt.h
Normal file
678
servers/rendering/rendering_server_wrap_mt.h
Normal file
|
|
@ -0,0 +1,678 @@
|
|||
/*************************************************************************/
|
||||
/* rendering_server_wrap_mt.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef RENDERING_SERVER_WRAP_MT_H
|
||||
#define RENDERING_SERVER_WRAP_MT_H
|
||||
|
||||
#include "core/command_queue_mt.h"
|
||||
#include "core/os/thread.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
class RenderingServerWrapMT : public RenderingServer {
|
||||
|
||||
// the real visual server
|
||||
mutable RenderingServer *rendering_server;
|
||||
|
||||
mutable CommandQueueMT command_queue;
|
||||
|
||||
static void _thread_callback(void *_instance);
|
||||
void thread_loop();
|
||||
|
||||
Thread::ID server_thread;
|
||||
volatile bool exit;
|
||||
Thread *thread;
|
||||
volatile bool draw_thread_up;
|
||||
bool create_thread;
|
||||
|
||||
uint64_t draw_pending;
|
||||
void thread_draw(bool p_swap_buffers, double frame_step);
|
||||
void thread_flush();
|
||||
|
||||
void thread_exit();
|
||||
|
||||
Mutex alloc_mutex;
|
||||
|
||||
int pool_max_size;
|
||||
|
||||
//#define DEBUG_SYNC
|
||||
|
||||
static RenderingServerWrapMT *singleton_mt;
|
||||
|
||||
#ifdef DEBUG_SYNC
|
||||
#define SYNC_DEBUG print_line("sync on: " + String(__FUNCTION__));
|
||||
#else
|
||||
#define SYNC_DEBUG
|
||||
#endif
|
||||
|
||||
public:
|
||||
#define ServerName RenderingServer
|
||||
#define ServerNameWrapMT RenderingServerWrapMT
|
||||
#define server_name rendering_server
|
||||
#include "servers/server_wrap_mt_common.h"
|
||||
|
||||
//these go pass-through, as they can be called from any thread
|
||||
virtual RID texture_2d_create(const Ref<Image> &p_image) { return rendering_server->texture_2d_create(p_image); }
|
||||
virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, TextureLayeredType p_layered_type) { return rendering_server->texture_2d_layered_create(p_layers, p_layered_type); }
|
||||
virtual RID texture_3d_create(const Vector<Ref<Image>> &p_slices) { return rendering_server->texture_3d_create(p_slices); }
|
||||
virtual RID texture_proxy_create(RID p_base) { return rendering_server->texture_proxy_create(p_base); }
|
||||
|
||||
//goes pass-through
|
||||
virtual void texture_2d_update_immediate(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) { rendering_server->texture_2d_update_immediate(p_texture, p_image, p_layer); }
|
||||
//these go through command queue if they are in another thread
|
||||
FUNC3(texture_2d_update, RID, const Ref<Image> &, int)
|
||||
FUNC4(texture_3d_update, RID, const Ref<Image> &, int, int)
|
||||
FUNC2(texture_proxy_update, RID, RID)
|
||||
|
||||
//these also go pass-through
|
||||
virtual RID texture_2d_placeholder_create() { return rendering_server->texture_2d_placeholder_create(); }
|
||||
virtual RID texture_2d_layered_placeholder_create() { return rendering_server->texture_2d_layered_placeholder_create(); }
|
||||
virtual RID texture_3d_placeholder_create() { return rendering_server->texture_3d_placeholder_create(); }
|
||||
|
||||
FUNC1RC(Ref<Image>, texture_2d_get, RID)
|
||||
FUNC2RC(Ref<Image>, texture_2d_layer_get, RID, int)
|
||||
FUNC3RC(Ref<Image>, texture_3d_slice_get, RID, int, int)
|
||||
|
||||
FUNC2(texture_replace, RID, RID)
|
||||
|
||||
FUNC3(texture_set_size_override, RID, int, int)
|
||||
// FIXME: Disabled during Vulkan refactoring, should be ported.
|
||||
#if 0
|
||||
FUNC2(texture_bind, RID, uint32_t)
|
||||
#endif
|
||||
|
||||
FUNC3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
|
||||
FUNC3(texture_set_detect_normal_callback, RID, TextureDetectCallback, void *)
|
||||
FUNC3(texture_set_detect_roughness_callback, RID, TextureDetectRoughnessCallback, void *)
|
||||
|
||||
FUNC2(texture_set_path, RID, const String &)
|
||||
FUNC1RC(String, texture_get_path, RID)
|
||||
FUNC1S(texture_debug_usage, List<TextureInfo> *)
|
||||
|
||||
FUNC2(texture_set_force_redraw_if_visible, RID, bool)
|
||||
|
||||
/* SHADER API */
|
||||
|
||||
FUNCRID(shader)
|
||||
|
||||
FUNC2(shader_set_code, RID, const String &)
|
||||
FUNC1RC(String, shader_get_code, RID)
|
||||
|
||||
FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *)
|
||||
|
||||
FUNC3(shader_set_default_texture_param, RID, const StringName &, RID)
|
||||
FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &)
|
||||
FUNC2RC(Variant, shader_get_param_default, RID, const StringName &)
|
||||
|
||||
/* COMMON MATERIAL API */
|
||||
|
||||
FUNCRID(material)
|
||||
|
||||
FUNC2(material_set_shader, RID, RID)
|
||||
|
||||
FUNC3(material_set_param, RID, const StringName &, const Variant &)
|
||||
FUNC2RC(Variant, material_get_param, RID, const StringName &)
|
||||
|
||||
FUNC2(material_set_render_priority, RID, int)
|
||||
FUNC2(material_set_next_pass, RID, RID)
|
||||
|
||||
/* MESH API */
|
||||
|
||||
virtual RID mesh_create_from_surfaces(const Vector<SurfaceData> &p_surfaces) {
|
||||
return rendering_server->mesh_create_from_surfaces(p_surfaces);
|
||||
}
|
||||
|
||||
FUNCRID(mesh)
|
||||
|
||||
FUNC2(mesh_add_surface, RID, const SurfaceData &)
|
||||
|
||||
FUNC1RC(int, mesh_get_blend_shape_count, RID)
|
||||
|
||||
FUNC2(mesh_set_blend_shape_mode, RID, BlendShapeMode)
|
||||
FUNC1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID)
|
||||
|
||||
FUNC4(mesh_surface_update_region, RID, int, int, const Vector<uint8_t> &)
|
||||
|
||||
FUNC3(mesh_surface_set_material, RID, int, RID)
|
||||
FUNC2RC(RID, mesh_surface_get_material, RID, int)
|
||||
|
||||
FUNC2RC(SurfaceData, mesh_get_surface, RID, int)
|
||||
|
||||
FUNC1RC(int, mesh_get_surface_count, RID)
|
||||
|
||||
FUNC2(mesh_set_custom_aabb, RID, const AABB &)
|
||||
FUNC1RC(AABB, mesh_get_custom_aabb, RID)
|
||||
|
||||
FUNC1(mesh_clear, RID)
|
||||
|
||||
/* MULTIMESH API */
|
||||
|
||||
FUNCRID(multimesh)
|
||||
|
||||
FUNC5(multimesh_allocate, RID, int, MultimeshTransformFormat, bool, bool)
|
||||
FUNC1RC(int, multimesh_get_instance_count, RID)
|
||||
|
||||
FUNC2(multimesh_set_mesh, RID, RID)
|
||||
FUNC3(multimesh_instance_set_transform, RID, int, const Transform &)
|
||||
FUNC3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &)
|
||||
FUNC3(multimesh_instance_set_color, RID, int, const Color &)
|
||||
FUNC3(multimesh_instance_set_custom_data, RID, int, const Color &)
|
||||
|
||||
FUNC1RC(RID, multimesh_get_mesh, RID)
|
||||
FUNC1RC(AABB, multimesh_get_aabb, RID)
|
||||
|
||||
FUNC2RC(Transform, multimesh_instance_get_transform, RID, int)
|
||||
FUNC2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int)
|
||||
FUNC2RC(Color, multimesh_instance_get_color, RID, int)
|
||||
FUNC2RC(Color, multimesh_instance_get_custom_data, RID, int)
|
||||
|
||||
FUNC2(multimesh_set_buffer, RID, const Vector<float> &)
|
||||
FUNC1RC(Vector<float>, multimesh_get_buffer, RID)
|
||||
|
||||
FUNC2(multimesh_set_visible_instances, RID, int)
|
||||
FUNC1RC(int, multimesh_get_visible_instances, RID)
|
||||
|
||||
/* IMMEDIATE API */
|
||||
|
||||
FUNCRID(immediate)
|
||||
FUNC3(immediate_begin, RID, PrimitiveType, RID)
|
||||
FUNC2(immediate_vertex, RID, const Vector3 &)
|
||||
FUNC2(immediate_normal, RID, const Vector3 &)
|
||||
FUNC2(immediate_tangent, RID, const Plane &)
|
||||
FUNC2(immediate_color, RID, const Color &)
|
||||
FUNC2(immediate_uv, RID, const Vector2 &)
|
||||
FUNC2(immediate_uv2, RID, const Vector2 &)
|
||||
FUNC1(immediate_end, RID)
|
||||
FUNC1(immediate_clear, RID)
|
||||
FUNC2(immediate_set_material, RID, RID)
|
||||
FUNC1RC(RID, immediate_get_material, RID)
|
||||
|
||||
/* SKELETON API */
|
||||
|
||||
FUNCRID(skeleton)
|
||||
FUNC3(skeleton_allocate, RID, int, bool)
|
||||
FUNC1RC(int, skeleton_get_bone_count, RID)
|
||||
FUNC3(skeleton_bone_set_transform, RID, int, const Transform &)
|
||||
FUNC2RC(Transform, skeleton_bone_get_transform, RID, int)
|
||||
FUNC3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &)
|
||||
FUNC2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int)
|
||||
FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &)
|
||||
|
||||
/* Light API */
|
||||
|
||||
FUNCRID(directional_light)
|
||||
FUNCRID(omni_light)
|
||||
FUNCRID(spot_light)
|
||||
|
||||
FUNC2(light_set_color, RID, const Color &)
|
||||
FUNC3(light_set_param, RID, LightParam, float)
|
||||
FUNC2(light_set_shadow, RID, bool)
|
||||
FUNC2(light_set_shadow_color, RID, const Color &)
|
||||
FUNC2(light_set_projector, RID, RID)
|
||||
FUNC2(light_set_negative, RID, bool)
|
||||
FUNC2(light_set_cull_mask, RID, uint32_t)
|
||||
FUNC2(light_set_reverse_cull_face_mode, RID, bool)
|
||||
FUNC2(light_set_use_gi, RID, bool)
|
||||
|
||||
FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode)
|
||||
|
||||
FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode)
|
||||
FUNC2(light_directional_set_blend_splits, RID, bool)
|
||||
FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode)
|
||||
|
||||
/* PROBE API */
|
||||
|
||||
FUNCRID(reflection_probe)
|
||||
|
||||
FUNC2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode)
|
||||
FUNC2(reflection_probe_set_intensity, RID, float)
|
||||
FUNC2(reflection_probe_set_interior_ambient, RID, const Color &)
|
||||
FUNC2(reflection_probe_set_interior_ambient_energy, RID, float)
|
||||
FUNC2(reflection_probe_set_interior_ambient_probe_contribution, RID, float)
|
||||
FUNC2(reflection_probe_set_max_distance, RID, float)
|
||||
FUNC2(reflection_probe_set_extents, RID, const Vector3 &)
|
||||
FUNC2(reflection_probe_set_origin_offset, RID, const Vector3 &)
|
||||
FUNC2(reflection_probe_set_as_interior, RID, bool)
|
||||
FUNC2(reflection_probe_set_enable_box_projection, RID, bool)
|
||||
FUNC2(reflection_probe_set_enable_shadows, RID, bool)
|
||||
FUNC2(reflection_probe_set_cull_mask, RID, uint32_t)
|
||||
FUNC2(reflection_probe_set_resolution, RID, int)
|
||||
|
||||
/* BAKED LIGHT API */
|
||||
|
||||
FUNCRID(gi_probe)
|
||||
|
||||
FUNC8(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<uint8_t> &, const Vector<int> &)
|
||||
|
||||
FUNC1RC(AABB, gi_probe_get_bounds, RID)
|
||||
FUNC1RC(Vector3i, gi_probe_get_octree_size, RID)
|
||||
FUNC1RC(Vector<uint8_t>, gi_probe_get_octree_cells, RID)
|
||||
FUNC1RC(Vector<uint8_t>, gi_probe_get_data_cells, RID)
|
||||
FUNC1RC(Vector<uint8_t>, gi_probe_get_distance_field, RID)
|
||||
FUNC1RC(Vector<int>, gi_probe_get_level_counts, RID)
|
||||
FUNC1RC(Transform, gi_probe_get_to_cell_xform, RID)
|
||||
|
||||
FUNC2(gi_probe_set_dynamic_range, RID, float)
|
||||
FUNC1RC(float, gi_probe_get_dynamic_range, RID)
|
||||
|
||||
FUNC2(gi_probe_set_propagation, RID, float)
|
||||
FUNC1RC(float, gi_probe_get_propagation, RID)
|
||||
|
||||
FUNC2(gi_probe_set_energy, RID, float)
|
||||
FUNC1RC(float, gi_probe_get_energy, RID)
|
||||
|
||||
FUNC2(gi_probe_set_ao, RID, float)
|
||||
FUNC1RC(float, gi_probe_get_ao, RID)
|
||||
|
||||
FUNC2(gi_probe_set_ao_size, RID, float)
|
||||
FUNC1RC(float, gi_probe_get_ao_size, RID)
|
||||
|
||||
FUNC2(gi_probe_set_bias, RID, float)
|
||||
FUNC1RC(float, gi_probe_get_bias, RID)
|
||||
|
||||
FUNC2(gi_probe_set_normal_bias, RID, float)
|
||||
FUNC1RC(float, gi_probe_get_normal_bias, RID)
|
||||
|
||||
FUNC2(gi_probe_set_interior, RID, bool)
|
||||
FUNC1RC(bool, gi_probe_is_interior, RID)
|
||||
|
||||
FUNC2(gi_probe_set_use_two_bounces, RID, bool)
|
||||
FUNC1RC(bool, gi_probe_is_using_two_bounces, RID)
|
||||
|
||||
FUNC2(gi_probe_set_anisotropy_strength, RID, float)
|
||||
FUNC1RC(float, gi_probe_get_anisotropy_strength, RID)
|
||||
|
||||
/* LIGHTMAP CAPTURE */
|
||||
|
||||
FUNCRID(lightmap_capture)
|
||||
|
||||
FUNC2(lightmap_capture_set_bounds, RID, const AABB &)
|
||||
FUNC1RC(AABB, lightmap_capture_get_bounds, RID)
|
||||
|
||||
FUNC2(lightmap_capture_set_octree, RID, const Vector<uint8_t> &)
|
||||
FUNC1RC(Vector<uint8_t>, lightmap_capture_get_octree, RID)
|
||||
FUNC2(lightmap_capture_set_octree_cell_transform, RID, const Transform &)
|
||||
FUNC1RC(Transform, lightmap_capture_get_octree_cell_transform, RID)
|
||||
FUNC2(lightmap_capture_set_octree_cell_subdiv, RID, int)
|
||||
FUNC1RC(int, lightmap_capture_get_octree_cell_subdiv, RID)
|
||||
FUNC2(lightmap_capture_set_energy, RID, float)
|
||||
FUNC1RC(float, lightmap_capture_get_energy, RID)
|
||||
|
||||
/* PARTICLES */
|
||||
|
||||
FUNCRID(particles)
|
||||
|
||||
FUNC2(particles_set_emitting, RID, bool)
|
||||
FUNC1R(bool, particles_get_emitting, RID)
|
||||
FUNC2(particles_set_amount, RID, int)
|
||||
FUNC2(particles_set_lifetime, RID, float)
|
||||
FUNC2(particles_set_one_shot, RID, bool)
|
||||
FUNC2(particles_set_pre_process_time, RID, float)
|
||||
FUNC2(particles_set_explosiveness_ratio, RID, float)
|
||||
FUNC2(particles_set_randomness_ratio, RID, float)
|
||||
FUNC2(particles_set_custom_aabb, RID, const AABB &)
|
||||
FUNC2(particles_set_speed_scale, RID, float)
|
||||
FUNC2(particles_set_use_local_coordinates, RID, bool)
|
||||
FUNC2(particles_set_process_material, RID, RID)
|
||||
FUNC2(particles_set_fixed_fps, RID, int)
|
||||
FUNC2(particles_set_fractional_delta, RID, bool)
|
||||
FUNC1R(bool, particles_is_inactive, RID)
|
||||
FUNC1(particles_request_process, RID)
|
||||
FUNC1(particles_restart, RID)
|
||||
|
||||
FUNC2(particles_set_draw_order, RID, RS::ParticlesDrawOrder)
|
||||
|
||||
FUNC2(particles_set_draw_passes, RID, int)
|
||||
FUNC3(particles_set_draw_pass_mesh, RID, int, RID)
|
||||
FUNC2(particles_set_emission_transform, RID, const Transform &)
|
||||
|
||||
FUNC1R(AABB, particles_get_current_aabb, RID)
|
||||
|
||||
/* CAMERA API */
|
||||
|
||||
FUNCRID(camera)
|
||||
FUNC4(camera_set_perspective, RID, float, float, float)
|
||||
FUNC4(camera_set_orthogonal, RID, float, float, float)
|
||||
FUNC5(camera_set_frustum, RID, float, Vector2, float, float)
|
||||
FUNC2(camera_set_transform, RID, const Transform &)
|
||||
FUNC2(camera_set_cull_mask, RID, uint32_t)
|
||||
FUNC2(camera_set_environment, RID, RID)
|
||||
FUNC2(camera_set_camera_effects, RID, RID)
|
||||
FUNC2(camera_set_use_vertical_aspect, RID, bool)
|
||||
|
||||
/* VIEWPORT TARGET API */
|
||||
|
||||
FUNCRID(viewport)
|
||||
|
||||
FUNC2(viewport_set_use_arvr, RID, bool)
|
||||
|
||||
FUNC3(viewport_set_size, RID, int, int)
|
||||
|
||||
FUNC2(viewport_set_active, RID, bool)
|
||||
FUNC2(viewport_set_parent_viewport, RID, RID)
|
||||
|
||||
FUNC2(viewport_set_clear_mode, RID, ViewportClearMode)
|
||||
|
||||
FUNC3(viewport_attach_to_screen, RID, const Rect2 &, DisplayServer::WindowID)
|
||||
FUNC2(viewport_set_render_direct_to_screen, RID, bool)
|
||||
|
||||
FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
|
||||
|
||||
FUNC1RC(RID, viewport_get_texture, RID)
|
||||
|
||||
FUNC2(viewport_set_hide_scenario, RID, bool)
|
||||
FUNC2(viewport_set_hide_canvas, RID, bool)
|
||||
FUNC2(viewport_set_disable_environment, RID, bool)
|
||||
|
||||
FUNC2(viewport_attach_camera, RID, RID)
|
||||
FUNC2(viewport_set_scenario, RID, RID)
|
||||
FUNC2(viewport_attach_canvas, RID, RID)
|
||||
|
||||
FUNC2(viewport_remove_canvas, RID, RID)
|
||||
FUNC3(viewport_set_canvas_transform, RID, RID, const Transform2D &)
|
||||
FUNC2(viewport_set_transparent_background, RID, bool)
|
||||
|
||||
FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
|
||||
FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
|
||||
FUNC2(viewport_set_shadow_atlas_size, RID, int)
|
||||
FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
|
||||
FUNC2(viewport_set_msaa, RID, ViewportMSAA)
|
||||
|
||||
//this passes directly to avoid stalling, but it's pretty dangerous, so don't call after freeing a viewport
|
||||
virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) {
|
||||
return rendering_server->viewport_get_render_info(p_viewport, p_info);
|
||||
}
|
||||
|
||||
FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw)
|
||||
|
||||
FUNC1(directional_shadow_atlas_set_size, int)
|
||||
|
||||
/* SKY API */
|
||||
|
||||
FUNCRID(sky)
|
||||
FUNC2(sky_set_radiance_size, RID, int)
|
||||
FUNC2(sky_set_mode, RID, SkyMode)
|
||||
FUNC2(sky_set_material, RID, RID)
|
||||
|
||||
/* ENVIRONMENT API */
|
||||
|
||||
FUNCRID(environment)
|
||||
|
||||
FUNC2(environment_set_background, RID, EnvironmentBG)
|
||||
FUNC2(environment_set_sky, RID, RID)
|
||||
FUNC2(environment_set_sky_custom_fov, RID, float)
|
||||
FUNC2(environment_set_sky_orientation, RID, const Basis &)
|
||||
FUNC2(environment_set_bg_color, RID, const Color &)
|
||||
FUNC2(environment_set_bg_energy, RID, float)
|
||||
FUNC2(environment_set_canvas_max_layer, RID, int)
|
||||
FUNC7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &)
|
||||
|
||||
// FIXME: Disabled during Vulkan refactoring, should be ported.
|
||||
#if 0
|
||||
FUNC2(environment_set_camera_feed_id, RID, int)
|
||||
#endif
|
||||
FUNC7(environment_set_ssr, RID, bool, int, float, float, float, bool)
|
||||
FUNC9(environment_set_ssao, RID, bool, float, float, float, float, float, EnvironmentSSAOBlur, float)
|
||||
|
||||
FUNC2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool)
|
||||
|
||||
FUNC12(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool)
|
||||
|
||||
FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
|
||||
|
||||
FUNC6(environment_set_adjustment, RID, bool, float, float, float, RID)
|
||||
|
||||
FUNC5(environment_set_fog, RID, bool, const Color &, const Color &, float)
|
||||
FUNC7(environment_set_fog_depth, RID, bool, float, float, float, bool, float)
|
||||
FUNC5(environment_set_fog_height, RID, bool, float, float, float)
|
||||
|
||||
FUNC2(screen_space_roughness_limiter_set_active, bool, float)
|
||||
|
||||
FUNCRID(camera_effects)
|
||||
|
||||
FUNC2(camera_effects_set_dof_blur_quality, DOFBlurQuality, bool)
|
||||
FUNC1(camera_effects_set_dof_blur_bokeh_shape, DOFBokehShape)
|
||||
|
||||
FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
|
||||
FUNC3(camera_effects_set_custom_exposure, RID, bool, float)
|
||||
|
||||
FUNCRID(scenario)
|
||||
|
||||
FUNC2(scenario_set_debug, RID, ScenarioDebugMode)
|
||||
FUNC2(scenario_set_environment, RID, RID)
|
||||
FUNC2(scenario_set_camera_effects, RID, RID)
|
||||
FUNC2(scenario_set_fallback_environment, RID, RID)
|
||||
|
||||
/* INSTANCING API */
|
||||
FUNCRID(instance)
|
||||
|
||||
FUNC2(instance_set_base, RID, RID)
|
||||
FUNC2(instance_set_scenario, RID, RID)
|
||||
FUNC2(instance_set_layer_mask, RID, uint32_t)
|
||||
FUNC2(instance_set_transform, RID, const Transform &)
|
||||
FUNC2(instance_attach_object_instance_id, RID, ObjectID)
|
||||
FUNC3(instance_set_blend_shape_weight, RID, int, float)
|
||||
FUNC3(instance_set_surface_material, RID, int, RID)
|
||||
FUNC2(instance_set_visible, RID, bool)
|
||||
FUNC3(instance_set_use_lightmap, RID, RID, RID)
|
||||
|
||||
FUNC2(instance_set_custom_aabb, RID, AABB)
|
||||
|
||||
FUNC2(instance_attach_skeleton, RID, RID)
|
||||
FUNC2(instance_set_exterior, RID, bool)
|
||||
|
||||
FUNC2(instance_set_extra_visibility_margin, RID, real_t)
|
||||
|
||||
// don't use these in a game!
|
||||
FUNC2RC(Vector<ObjectID>, instances_cull_aabb, const AABB &, RID)
|
||||
FUNC3RC(Vector<ObjectID>, instances_cull_ray, const Vector3 &, const Vector3 &, RID)
|
||||
FUNC2RC(Vector<ObjectID>, instances_cull_convex, const Vector<Plane> &, RID)
|
||||
|
||||
FUNC3(instance_geometry_set_flag, RID, InstanceFlags, bool)
|
||||
FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
|
||||
FUNC2(instance_geometry_set_material_override, RID, RID)
|
||||
|
||||
FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float)
|
||||
FUNC2(instance_geometry_set_as_instance_lod, RID, RID)
|
||||
|
||||
/* CANVAS (2D) */
|
||||
|
||||
FUNCRID(canvas)
|
||||
FUNC3(canvas_set_item_mirroring, RID, RID, const Point2 &)
|
||||
FUNC2(canvas_set_modulate, RID, const Color &)
|
||||
FUNC3(canvas_set_parent, RID, RID, float)
|
||||
FUNC1(canvas_set_disable_scale, bool)
|
||||
|
||||
FUNCRID(canvas_item)
|
||||
FUNC2(canvas_item_set_parent, RID, RID)
|
||||
|
||||
FUNC2(canvas_item_set_visible, RID, bool)
|
||||
FUNC2(canvas_item_set_light_mask, RID, int)
|
||||
|
||||
FUNC2(canvas_item_set_update_when_visible, RID, bool)
|
||||
|
||||
FUNC2(canvas_item_set_transform, RID, const Transform2D &)
|
||||
FUNC2(canvas_item_set_clip, RID, bool)
|
||||
FUNC2(canvas_item_set_distance_field_mode, RID, bool)
|
||||
FUNC3(canvas_item_set_custom_rect, RID, bool, const Rect2 &)
|
||||
FUNC2(canvas_item_set_modulate, RID, const Color &)
|
||||
FUNC2(canvas_item_set_self_modulate, RID, const Color &)
|
||||
|
||||
FUNC2(canvas_item_set_draw_behind_parent, RID, bool)
|
||||
|
||||
FUNC2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter)
|
||||
FUNC2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat)
|
||||
|
||||
FUNC5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float)
|
||||
FUNC4(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float)
|
||||
FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float)
|
||||
FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &)
|
||||
FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &)
|
||||
FUNC11(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
FUNC12(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, RID, RID, const Color &, bool, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
FUNC15(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
FUNC11(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
FUNC10(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
FUNC14(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
FUNC10(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
FUNC8(canvas_item_add_multimesh, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
FUNC8(canvas_item_add_particles, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat)
|
||||
FUNC2(canvas_item_add_set_transform, RID, const Transform2D &)
|
||||
FUNC2(canvas_item_add_clip_ignore, RID, bool)
|
||||
FUNC2(canvas_item_set_sort_children_by_y, RID, bool)
|
||||
FUNC2(canvas_item_set_z_index, RID, int)
|
||||
FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool)
|
||||
FUNC3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &)
|
||||
FUNC2(canvas_item_attach_skeleton, RID, RID)
|
||||
|
||||
FUNC1(canvas_item_clear, RID)
|
||||
FUNC2(canvas_item_set_draw_index, RID, int)
|
||||
|
||||
FUNC2(canvas_item_set_material, RID, RID)
|
||||
|
||||
FUNC2(canvas_item_set_use_parent_material, RID, bool)
|
||||
|
||||
FUNC0R(RID, canvas_light_create)
|
||||
FUNC2(canvas_light_attach_to_canvas, RID, RID)
|
||||
FUNC2(canvas_light_set_enabled, RID, bool)
|
||||
FUNC2(canvas_light_set_scale, RID, float)
|
||||
FUNC2(canvas_light_set_transform, RID, const Transform2D &)
|
||||
FUNC2(canvas_light_set_texture, RID, RID)
|
||||
FUNC2(canvas_light_set_texture_offset, RID, const Vector2 &)
|
||||
FUNC2(canvas_light_set_color, RID, const Color &)
|
||||
FUNC2(canvas_light_set_height, RID, float)
|
||||
FUNC2(canvas_light_set_energy, RID, float)
|
||||
FUNC3(canvas_light_set_z_range, RID, int, int)
|
||||
FUNC3(canvas_light_set_layer_range, RID, int, int)
|
||||
FUNC2(canvas_light_set_item_cull_mask, RID, int)
|
||||
FUNC2(canvas_light_set_item_shadow_cull_mask, RID, int)
|
||||
|
||||
FUNC2(canvas_light_set_mode, RID, CanvasLightMode)
|
||||
|
||||
FUNC2(canvas_light_set_shadow_enabled, RID, bool)
|
||||
FUNC2(canvas_light_set_shadow_buffer_size, RID, int)
|
||||
FUNC2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter)
|
||||
FUNC2(canvas_light_set_shadow_color, RID, const Color &)
|
||||
FUNC2(canvas_light_set_shadow_smooth, RID, float)
|
||||
|
||||
FUNCRID(canvas_light_occluder)
|
||||
FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID)
|
||||
FUNC2(canvas_light_occluder_set_enabled, RID, bool)
|
||||
FUNC2(canvas_light_occluder_set_polygon, RID, RID)
|
||||
FUNC2(canvas_light_occluder_set_transform, RID, const Transform2D &)
|
||||
FUNC2(canvas_light_occluder_set_light_mask, RID, int)
|
||||
|
||||
FUNCRID(canvas_occluder_polygon)
|
||||
FUNC3(canvas_occluder_polygon_set_shape, RID, const Vector<Vector2> &, bool)
|
||||
FUNC2(canvas_occluder_polygon_set_shape_as_lines, RID, const Vector<Vector2> &)
|
||||
|
||||
FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode)
|
||||
|
||||
/* BLACK BARS */
|
||||
|
||||
FUNC4(black_bars_set_margins, int, int, int, int)
|
||||
FUNC4(black_bars_set_images, RID, RID, RID, RID)
|
||||
|
||||
/* FREE */
|
||||
|
||||
FUNC1(free, RID)
|
||||
|
||||
/* EVENT QUEUING */
|
||||
|
||||
FUNC3(request_frame_drawn_callback, Object *, const StringName &, const Variant &)
|
||||
|
||||
virtual void init();
|
||||
virtual void finish();
|
||||
virtual void draw(bool p_swap_buffers, double frame_step);
|
||||
virtual void sync();
|
||||
FUNC0RC(bool, has_changed)
|
||||
|
||||
/* RENDER INFO */
|
||||
|
||||
//this passes directly to avoid stalling
|
||||
virtual int get_render_info(RenderInfo p_info) {
|
||||
return rendering_server->get_render_info(p_info);
|
||||
}
|
||||
|
||||
virtual String get_video_adapter_name() const {
|
||||
return rendering_server->get_video_adapter_name();
|
||||
}
|
||||
|
||||
virtual String get_video_adapter_vendor() const {
|
||||
return rendering_server->get_video_adapter_vendor();
|
||||
}
|
||||
|
||||
FUNC4(set_boot_image, const Ref<Image> &, const Color &, bool, bool)
|
||||
FUNC1(set_default_clear_color, const Color &)
|
||||
|
||||
FUNC0R(RID, get_test_cube)
|
||||
|
||||
FUNC1(set_debug_generate_wireframes, bool)
|
||||
|
||||
virtual bool has_feature(Features p_feature) const {
|
||||
return rendering_server->has_feature(p_feature);
|
||||
}
|
||||
virtual bool has_os_feature(const String &p_feature) const {
|
||||
return rendering_server->has_os_feature(p_feature);
|
||||
}
|
||||
|
||||
FUNC1(call_set_use_vsync, bool)
|
||||
|
||||
static void set_use_vsync_callback(bool p_enable);
|
||||
|
||||
virtual bool is_low_end() const {
|
||||
return rendering_server->is_low_end();
|
||||
}
|
||||
|
||||
virtual uint64_t get_frame_profile_frame() {
|
||||
return rendering_server->get_frame_profile_frame();
|
||||
}
|
||||
|
||||
virtual void set_frame_profiling_enabled(bool p_enabled) {
|
||||
rendering_server->set_frame_profiling_enabled(p_enabled);
|
||||
}
|
||||
|
||||
virtual Vector<FrameProfileArea> get_frame_profile() {
|
||||
return rendering_server->get_frame_profile();
|
||||
}
|
||||
|
||||
RenderingServerWrapMT(RenderingServer *p_contained, bool p_create_thread);
|
||||
~RenderingServerWrapMT();
|
||||
|
||||
#undef ServerName
|
||||
#undef ServerNameWrapMT
|
||||
#undef server_name
|
||||
};
|
||||
|
||||
#ifdef DEBUG_SYNC
|
||||
#undef DEBUG_SYNC
|
||||
#endif
|
||||
#undef SYNC_DEBUG
|
||||
|
||||
#endif
|
||||
7006
servers/rendering/shader_language.cpp
Normal file
7006
servers/rendering/shader_language.cpp
Normal file
File diff suppressed because it is too large
Load diff
900
servers/rendering/shader_language.h
Normal file
900
servers/rendering/shader_language.h
Normal file
|
|
@ -0,0 +1,900 @@
|
|||
/*************************************************************************/
|
||||
/* shader_language.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef SHADER_LANGUAGE_H
|
||||
#define SHADER_LANGUAGE_H
|
||||
|
||||
#include "core/list.h"
|
||||
#include "core/map.h"
|
||||
#include "core/script_language.h"
|
||||
#include "core/string_name.h"
|
||||
#include "core/typedefs.h"
|
||||
#include "core/ustring.h"
|
||||
#include "core/variant.h"
|
||||
|
||||
class ShaderLanguage {
|
||||
|
||||
public:
|
||||
enum TokenType {
|
||||
TK_EMPTY,
|
||||
TK_IDENTIFIER,
|
||||
TK_TRUE,
|
||||
TK_FALSE,
|
||||
TK_REAL_CONSTANT,
|
||||
TK_INT_CONSTANT,
|
||||
TK_TYPE_VOID,
|
||||
TK_TYPE_BOOL,
|
||||
TK_TYPE_BVEC2,
|
||||
TK_TYPE_BVEC3,
|
||||
TK_TYPE_BVEC4,
|
||||
TK_TYPE_INT,
|
||||
TK_TYPE_IVEC2,
|
||||
TK_TYPE_IVEC3,
|
||||
TK_TYPE_IVEC4,
|
||||
TK_TYPE_UINT,
|
||||
TK_TYPE_UVEC2,
|
||||
TK_TYPE_UVEC3,
|
||||
TK_TYPE_UVEC4,
|
||||
TK_TYPE_FLOAT,
|
||||
TK_TYPE_VEC2,
|
||||
TK_TYPE_VEC3,
|
||||
TK_TYPE_VEC4,
|
||||
TK_TYPE_MAT2,
|
||||
TK_TYPE_MAT3,
|
||||
TK_TYPE_MAT4,
|
||||
TK_TYPE_SAMPLER2D,
|
||||
TK_TYPE_ISAMPLER2D,
|
||||
TK_TYPE_USAMPLER2D,
|
||||
TK_TYPE_SAMPLER2DARRAY,
|
||||
TK_TYPE_ISAMPLER2DARRAY,
|
||||
TK_TYPE_USAMPLER2DARRAY,
|
||||
TK_TYPE_SAMPLER3D,
|
||||
TK_TYPE_ISAMPLER3D,
|
||||
TK_TYPE_USAMPLER3D,
|
||||
TK_TYPE_SAMPLERCUBE,
|
||||
TK_INTERPOLATION_FLAT,
|
||||
TK_INTERPOLATION_SMOOTH,
|
||||
TK_CONST,
|
||||
TK_STRUCT,
|
||||
TK_PRECISION_LOW,
|
||||
TK_PRECISION_MID,
|
||||
TK_PRECISION_HIGH,
|
||||
TK_OP_EQUAL,
|
||||
TK_OP_NOT_EQUAL,
|
||||
TK_OP_LESS,
|
||||
TK_OP_LESS_EQUAL,
|
||||
TK_OP_GREATER,
|
||||
TK_OP_GREATER_EQUAL,
|
||||
TK_OP_AND,
|
||||
TK_OP_OR,
|
||||
TK_OP_NOT,
|
||||
TK_OP_ADD,
|
||||
TK_OP_SUB,
|
||||
TK_OP_MUL,
|
||||
TK_OP_DIV,
|
||||
TK_OP_MOD,
|
||||
TK_OP_SHIFT_LEFT,
|
||||
TK_OP_SHIFT_RIGHT,
|
||||
TK_OP_ASSIGN,
|
||||
TK_OP_ASSIGN_ADD,
|
||||
TK_OP_ASSIGN_SUB,
|
||||
TK_OP_ASSIGN_MUL,
|
||||
TK_OP_ASSIGN_DIV,
|
||||
TK_OP_ASSIGN_MOD,
|
||||
TK_OP_ASSIGN_SHIFT_LEFT,
|
||||
TK_OP_ASSIGN_SHIFT_RIGHT,
|
||||
TK_OP_ASSIGN_BIT_AND,
|
||||
TK_OP_ASSIGN_BIT_OR,
|
||||
TK_OP_ASSIGN_BIT_XOR,
|
||||
TK_OP_BIT_AND,
|
||||
TK_OP_BIT_OR,
|
||||
TK_OP_BIT_XOR,
|
||||
TK_OP_BIT_INVERT,
|
||||
TK_OP_INCREMENT,
|
||||
TK_OP_DECREMENT,
|
||||
TK_CF_IF,
|
||||
TK_CF_ELSE,
|
||||
TK_CF_FOR,
|
||||
TK_CF_WHILE,
|
||||
TK_CF_DO,
|
||||
TK_CF_SWITCH,
|
||||
TK_CF_CASE,
|
||||
TK_CF_DEFAULT,
|
||||
TK_CF_BREAK,
|
||||
TK_CF_CONTINUE,
|
||||
TK_CF_RETURN,
|
||||
TK_CF_DISCARD,
|
||||
TK_BRACKET_OPEN,
|
||||
TK_BRACKET_CLOSE,
|
||||
TK_CURLY_BRACKET_OPEN,
|
||||
TK_CURLY_BRACKET_CLOSE,
|
||||
TK_PARENTHESIS_OPEN,
|
||||
TK_PARENTHESIS_CLOSE,
|
||||
TK_QUESTION,
|
||||
TK_COMMA,
|
||||
TK_COLON,
|
||||
TK_SEMICOLON,
|
||||
TK_PERIOD,
|
||||
TK_UNIFORM,
|
||||
TK_VARYING,
|
||||
TK_ARG_IN,
|
||||
TK_ARG_OUT,
|
||||
TK_ARG_INOUT,
|
||||
TK_RENDER_MODE,
|
||||
TK_HINT_WHITE_TEXTURE,
|
||||
TK_HINT_BLACK_TEXTURE,
|
||||
TK_HINT_NORMAL_TEXTURE,
|
||||
TK_HINT_ROUGHNESS_NORMAL_TEXTURE,
|
||||
TK_HINT_ROUGHNESS_R,
|
||||
TK_HINT_ROUGHNESS_G,
|
||||
TK_HINT_ROUGHNESS_B,
|
||||
TK_HINT_ROUGHNESS_A,
|
||||
TK_HINT_ROUGHNESS_GRAY,
|
||||
TK_HINT_ANISO_TEXTURE,
|
||||
TK_HINT_ALBEDO_TEXTURE,
|
||||
TK_HINT_BLACK_ALBEDO_TEXTURE,
|
||||
TK_HINT_COLOR,
|
||||
TK_HINT_RANGE,
|
||||
TK_FILTER_NEAREST,
|
||||
TK_FILTER_LINEAR,
|
||||
TK_FILTER_NEAREST_MIPMAP,
|
||||
TK_FILTER_LINEAR_MIPMAP,
|
||||
TK_FILTER_NEAREST_MIPMAP_ANISO,
|
||||
TK_FILTER_LINEAR_MIPMAP_ANISO,
|
||||
TK_REPEAT_ENABLE,
|
||||
TK_REPEAT_DISABLE,
|
||||
TK_SHADER_TYPE,
|
||||
TK_CURSOR,
|
||||
TK_ERROR,
|
||||
TK_EOF,
|
||||
TK_MAX
|
||||
};
|
||||
|
||||
/* COMPILER */
|
||||
|
||||
// lame work around to Apple defining this as a macro in 10.12 SDK
|
||||
#ifdef TYPE_BOOL
|
||||
#undef TYPE_BOOL
|
||||
#endif
|
||||
|
||||
enum DataType {
|
||||
TYPE_VOID,
|
||||
TYPE_BOOL,
|
||||
TYPE_BVEC2,
|
||||
TYPE_BVEC3,
|
||||
TYPE_BVEC4,
|
||||
TYPE_INT,
|
||||
TYPE_IVEC2,
|
||||
TYPE_IVEC3,
|
||||
TYPE_IVEC4,
|
||||
TYPE_UINT,
|
||||
TYPE_UVEC2,
|
||||
TYPE_UVEC3,
|
||||
TYPE_UVEC4,
|
||||
TYPE_FLOAT,
|
||||
TYPE_VEC2,
|
||||
TYPE_VEC3,
|
||||
TYPE_VEC4,
|
||||
TYPE_MAT2,
|
||||
TYPE_MAT3,
|
||||
TYPE_MAT4,
|
||||
TYPE_SAMPLER2D,
|
||||
TYPE_ISAMPLER2D,
|
||||
TYPE_USAMPLER2D,
|
||||
TYPE_SAMPLER2DARRAY,
|
||||
TYPE_ISAMPLER2DARRAY,
|
||||
TYPE_USAMPLER2DARRAY,
|
||||
TYPE_SAMPLER3D,
|
||||
TYPE_ISAMPLER3D,
|
||||
TYPE_USAMPLER3D,
|
||||
TYPE_SAMPLERCUBE,
|
||||
TYPE_STRUCT,
|
||||
};
|
||||
|
||||
enum DataPrecision {
|
||||
PRECISION_LOWP,
|
||||
PRECISION_MEDIUMP,
|
||||
PRECISION_HIGHP,
|
||||
PRECISION_DEFAULT,
|
||||
};
|
||||
|
||||
enum DataInterpolation {
|
||||
INTERPOLATION_FLAT,
|
||||
INTERPOLATION_SMOOTH,
|
||||
};
|
||||
|
||||
enum Operator {
|
||||
OP_EQUAL,
|
||||
OP_NOT_EQUAL,
|
||||
OP_LESS,
|
||||
OP_LESS_EQUAL,
|
||||
OP_GREATER,
|
||||
OP_GREATER_EQUAL,
|
||||
OP_AND,
|
||||
OP_OR,
|
||||
OP_NOT,
|
||||
OP_NEGATE,
|
||||
OP_ADD,
|
||||
OP_SUB,
|
||||
OP_MUL,
|
||||
OP_DIV,
|
||||
OP_MOD,
|
||||
OP_SHIFT_LEFT,
|
||||
OP_SHIFT_RIGHT,
|
||||
OP_ASSIGN,
|
||||
OP_ASSIGN_ADD,
|
||||
OP_ASSIGN_SUB,
|
||||
OP_ASSIGN_MUL,
|
||||
OP_ASSIGN_DIV,
|
||||
OP_ASSIGN_MOD,
|
||||
OP_ASSIGN_SHIFT_LEFT,
|
||||
OP_ASSIGN_SHIFT_RIGHT,
|
||||
OP_ASSIGN_BIT_AND,
|
||||
OP_ASSIGN_BIT_OR,
|
||||
OP_ASSIGN_BIT_XOR,
|
||||
OP_BIT_AND,
|
||||
OP_BIT_OR,
|
||||
OP_BIT_XOR,
|
||||
OP_BIT_INVERT,
|
||||
OP_INCREMENT,
|
||||
OP_DECREMENT,
|
||||
OP_SELECT_IF,
|
||||
OP_SELECT_ELSE, //used only internally, then only IF appears with 3 arguments
|
||||
OP_POST_INCREMENT,
|
||||
OP_POST_DECREMENT,
|
||||
OP_CALL,
|
||||
OP_CONSTRUCT,
|
||||
OP_STRUCT,
|
||||
OP_INDEX,
|
||||
OP_MAX
|
||||
};
|
||||
|
||||
enum FlowOperation {
|
||||
FLOW_OP_IF,
|
||||
FLOW_OP_RETURN,
|
||||
FLOW_OP_FOR,
|
||||
FLOW_OP_WHILE,
|
||||
FLOW_OP_DO,
|
||||
FLOW_OP_BREAK,
|
||||
FLOW_OP_SWITCH,
|
||||
FLOW_OP_CASE,
|
||||
FLOW_OP_DEFAULT,
|
||||
FLOW_OP_CONTINUE,
|
||||
FLOW_OP_DISCARD
|
||||
};
|
||||
|
||||
enum ArgumentQualifier {
|
||||
ARGUMENT_QUALIFIER_IN,
|
||||
ARGUMENT_QUALIFIER_OUT,
|
||||
ARGUMENT_QUALIFIER_INOUT,
|
||||
};
|
||||
|
||||
enum SubClassTag {
|
||||
TAG_GLOBAL,
|
||||
TAG_ARRAY,
|
||||
};
|
||||
|
||||
enum TextureFilter {
|
||||
FILTER_NEAREST,
|
||||
FILTER_LINEAR,
|
||||
FILTER_NEAREST_MIPMAP,
|
||||
FILTER_LINEAR_MIPMAP,
|
||||
FILTER_NEAREST_MIPMAP_ANISO,
|
||||
FILTER_LINEAR_MIPMAP_ANISO,
|
||||
FILTER_DEFAULT,
|
||||
};
|
||||
|
||||
enum TextureRepeat {
|
||||
REPEAT_DISABLE,
|
||||
REPEAT_ENABLE,
|
||||
REPEAT_DEFAULT,
|
||||
};
|
||||
|
||||
struct Node {
|
||||
Node *next;
|
||||
|
||||
enum Type {
|
||||
TYPE_SHADER,
|
||||
TYPE_FUNCTION,
|
||||
TYPE_BLOCK,
|
||||
TYPE_VARIABLE,
|
||||
TYPE_VARIABLE_DECLARATION,
|
||||
TYPE_CONSTANT,
|
||||
TYPE_OPERATOR,
|
||||
TYPE_CONTROL_FLOW,
|
||||
TYPE_MEMBER,
|
||||
TYPE_ARRAY,
|
||||
TYPE_ARRAY_DECLARATION,
|
||||
TYPE_ARRAY_CONSTRUCT,
|
||||
TYPE_STRUCT,
|
||||
};
|
||||
|
||||
Type type;
|
||||
|
||||
virtual DataType get_datatype() const { return TYPE_VOID; }
|
||||
virtual String get_datatype_name() const { return ""; }
|
||||
|
||||
Node(Type t) :
|
||||
next(NULL),
|
||||
type(t) {}
|
||||
virtual ~Node() {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
T *alloc_node() {
|
||||
T *node = memnew(T);
|
||||
node->next = nodes;
|
||||
nodes = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
Node *nodes;
|
||||
|
||||
struct OperatorNode : public Node {
|
||||
DataType return_cache;
|
||||
DataPrecision return_precision_cache;
|
||||
Operator op;
|
||||
StringName struct_name;
|
||||
Vector<Node *> arguments;
|
||||
virtual DataType get_datatype() const { return return_cache; }
|
||||
virtual String get_datatype_name() const { return String(struct_name); }
|
||||
|
||||
OperatorNode() :
|
||||
Node(TYPE_OPERATOR),
|
||||
return_cache(TYPE_VOID),
|
||||
return_precision_cache(PRECISION_DEFAULT),
|
||||
op(OP_EQUAL),
|
||||
struct_name("") {}
|
||||
};
|
||||
|
||||
struct VariableNode : public Node {
|
||||
DataType datatype_cache;
|
||||
StringName name;
|
||||
StringName struct_name;
|
||||
virtual DataType get_datatype() const { return datatype_cache; }
|
||||
virtual String get_datatype_name() const { return String(struct_name); }
|
||||
bool is_const;
|
||||
|
||||
VariableNode() :
|
||||
Node(TYPE_VARIABLE),
|
||||
datatype_cache(TYPE_VOID),
|
||||
is_const(false) {}
|
||||
};
|
||||
|
||||
struct VariableDeclarationNode : public Node {
|
||||
DataPrecision precision;
|
||||
DataType datatype;
|
||||
String struct_name;
|
||||
bool is_const;
|
||||
|
||||
struct Declaration {
|
||||
StringName name;
|
||||
Node *initializer;
|
||||
};
|
||||
|
||||
Vector<Declaration> declarations;
|
||||
virtual DataType get_datatype() const { return datatype; }
|
||||
|
||||
VariableDeclarationNode() :
|
||||
Node(TYPE_VARIABLE_DECLARATION),
|
||||
precision(PRECISION_DEFAULT),
|
||||
datatype(TYPE_VOID),
|
||||
is_const(false) {}
|
||||
};
|
||||
|
||||
struct ArrayNode : public Node {
|
||||
DataType datatype_cache;
|
||||
StringName struct_name;
|
||||
StringName name;
|
||||
Node *index_expression;
|
||||
Node *call_expression;
|
||||
bool is_const;
|
||||
|
||||
virtual DataType get_datatype() const { return datatype_cache; }
|
||||
virtual String get_datatype_name() const { return String(struct_name); }
|
||||
|
||||
ArrayNode() :
|
||||
Node(TYPE_ARRAY),
|
||||
datatype_cache(TYPE_VOID),
|
||||
index_expression(NULL),
|
||||
call_expression(NULL),
|
||||
is_const(false) {}
|
||||
};
|
||||
|
||||
struct ArrayConstructNode : public Node {
|
||||
DataType datatype;
|
||||
String struct_name;
|
||||
Vector<Node *> initializer;
|
||||
|
||||
ArrayConstructNode() :
|
||||
Node(TYPE_ARRAY_CONSTRUCT),
|
||||
datatype(TYPE_VOID) {
|
||||
}
|
||||
};
|
||||
|
||||
struct ArrayDeclarationNode : public Node {
|
||||
DataPrecision precision;
|
||||
DataType datatype;
|
||||
String struct_name;
|
||||
bool is_const;
|
||||
|
||||
struct Declaration {
|
||||
StringName name;
|
||||
uint32_t size;
|
||||
Vector<Node *> initializer;
|
||||
};
|
||||
|
||||
Vector<Declaration> declarations;
|
||||
virtual DataType get_datatype() const { return datatype; }
|
||||
|
||||
ArrayDeclarationNode() :
|
||||
Node(TYPE_ARRAY_DECLARATION),
|
||||
precision(PRECISION_DEFAULT),
|
||||
datatype(TYPE_VOID),
|
||||
is_const(false) {}
|
||||
};
|
||||
|
||||
struct ConstantNode : public Node {
|
||||
DataType datatype;
|
||||
|
||||
union Value {
|
||||
bool boolean;
|
||||
float real;
|
||||
int32_t sint;
|
||||
uint32_t uint;
|
||||
};
|
||||
|
||||
Vector<Value> values;
|
||||
virtual DataType get_datatype() const { return datatype; }
|
||||
|
||||
ConstantNode() :
|
||||
Node(TYPE_CONSTANT),
|
||||
datatype(TYPE_VOID) {}
|
||||
};
|
||||
|
||||
struct FunctionNode;
|
||||
|
||||
struct BlockNode : public Node {
|
||||
FunctionNode *parent_function;
|
||||
BlockNode *parent_block;
|
||||
|
||||
enum BlockType {
|
||||
BLOCK_TYPE_STANDART,
|
||||
BLOCK_TYPE_SWITCH,
|
||||
BLOCK_TYPE_CASE,
|
||||
BLOCK_TYPE_DEFAULT,
|
||||
};
|
||||
|
||||
int block_type;
|
||||
SubClassTag block_tag;
|
||||
|
||||
struct Variable {
|
||||
DataType type;
|
||||
StringName struct_name;
|
||||
DataPrecision precision;
|
||||
int line; //for completion
|
||||
int array_size;
|
||||
bool is_const;
|
||||
};
|
||||
|
||||
Map<StringName, Variable> variables;
|
||||
List<Node *> statements;
|
||||
bool single_statement;
|
||||
|
||||
BlockNode() :
|
||||
Node(TYPE_BLOCK),
|
||||
parent_function(NULL),
|
||||
parent_block(NULL),
|
||||
block_type(BLOCK_TYPE_STANDART),
|
||||
block_tag(SubClassTag::TAG_GLOBAL),
|
||||
single_statement(false) {}
|
||||
};
|
||||
|
||||
struct ControlFlowNode : public Node {
|
||||
FlowOperation flow_op;
|
||||
Vector<Node *> expressions;
|
||||
Vector<BlockNode *> blocks;
|
||||
|
||||
ControlFlowNode() :
|
||||
Node(TYPE_CONTROL_FLOW),
|
||||
flow_op(FLOW_OP_IF) {}
|
||||
};
|
||||
|
||||
struct MemberNode : public Node {
|
||||
DataType basetype;
|
||||
bool basetype_const;
|
||||
StringName base_struct_name;
|
||||
DataPrecision precision;
|
||||
DataType datatype;
|
||||
int array_size;
|
||||
StringName struct_name;
|
||||
StringName name;
|
||||
Node *owner;
|
||||
Node *index_expression;
|
||||
bool has_swizzling_duplicates;
|
||||
|
||||
virtual DataType get_datatype() const { return datatype; }
|
||||
virtual String get_datatype_name() const { return String(struct_name); }
|
||||
|
||||
MemberNode() :
|
||||
Node(TYPE_MEMBER),
|
||||
basetype(TYPE_VOID),
|
||||
basetype_const(false),
|
||||
datatype(TYPE_VOID),
|
||||
array_size(0),
|
||||
owner(NULL),
|
||||
index_expression(NULL),
|
||||
has_swizzling_duplicates(false) {}
|
||||
};
|
||||
|
||||
struct StructNode : public Node {
|
||||
|
||||
List<MemberNode *> members;
|
||||
StructNode() :
|
||||
Node(TYPE_STRUCT) {}
|
||||
};
|
||||
|
||||
struct FunctionNode : public Node {
|
||||
|
||||
struct Argument {
|
||||
ArgumentQualifier qualifier;
|
||||
StringName name;
|
||||
DataType type;
|
||||
StringName type_str;
|
||||
DataPrecision precision;
|
||||
//for passing textures as arguments
|
||||
bool tex_argument_check;
|
||||
TextureFilter tex_argument_filter;
|
||||
TextureRepeat tex_argument_repeat;
|
||||
bool tex_builtin_check;
|
||||
StringName tex_builtin;
|
||||
|
||||
Map<StringName, Set<int>> tex_argument_connect;
|
||||
};
|
||||
|
||||
StringName name;
|
||||
DataType return_type;
|
||||
StringName return_struct_name;
|
||||
DataPrecision return_precision;
|
||||
Vector<Argument> arguments;
|
||||
BlockNode *body;
|
||||
bool can_discard;
|
||||
|
||||
FunctionNode() :
|
||||
Node(TYPE_FUNCTION),
|
||||
return_type(TYPE_VOID),
|
||||
return_precision(PRECISION_DEFAULT),
|
||||
body(NULL),
|
||||
can_discard(false) {}
|
||||
};
|
||||
|
||||
struct ShaderNode : public Node {
|
||||
|
||||
struct Constant {
|
||||
DataType type;
|
||||
StringName type_str;
|
||||
DataPrecision precision;
|
||||
ConstantNode *initializer;
|
||||
};
|
||||
|
||||
struct Function {
|
||||
StringName name;
|
||||
FunctionNode *function;
|
||||
Set<StringName> uses_function;
|
||||
bool callable;
|
||||
};
|
||||
|
||||
struct Struct {
|
||||
StringName name;
|
||||
StructNode *shader_struct;
|
||||
};
|
||||
|
||||
struct Varying {
|
||||
DataType type;
|
||||
DataInterpolation interpolation;
|
||||
DataPrecision precision;
|
||||
int array_size;
|
||||
|
||||
Varying() :
|
||||
type(TYPE_VOID),
|
||||
interpolation(INTERPOLATION_FLAT),
|
||||
precision(PRECISION_DEFAULT),
|
||||
array_size(0) {}
|
||||
};
|
||||
|
||||
struct Uniform {
|
||||
enum Hint {
|
||||
HINT_NONE,
|
||||
HINT_COLOR,
|
||||
HINT_RANGE,
|
||||
HINT_ALBEDO,
|
||||
HINT_BLACK_ALBEDO,
|
||||
HINT_NORMAL,
|
||||
HINT_ROUGHNESS_NORMAL,
|
||||
HINT_ROUGHNESS_R,
|
||||
HINT_ROUGHNESS_G,
|
||||
HINT_ROUGHNESS_B,
|
||||
HINT_ROUGHNESS_A,
|
||||
HINT_ROUGHNESS_GRAY,
|
||||
HINT_BLACK,
|
||||
HINT_WHITE,
|
||||
HINT_ANISO,
|
||||
HINT_MAX
|
||||
};
|
||||
|
||||
int order;
|
||||
int texture_order;
|
||||
DataType type;
|
||||
DataPrecision precision;
|
||||
Vector<ConstantNode::Value> default_value;
|
||||
Hint hint;
|
||||
TextureFilter filter;
|
||||
TextureRepeat repeat;
|
||||
float hint_range[3];
|
||||
|
||||
Uniform() :
|
||||
order(0),
|
||||
texture_order(0),
|
||||
type(TYPE_VOID),
|
||||
precision(PRECISION_DEFAULT),
|
||||
hint(HINT_NONE),
|
||||
filter(FILTER_DEFAULT),
|
||||
repeat(REPEAT_DEFAULT) {
|
||||
hint_range[0] = 0.0f;
|
||||
hint_range[1] = 1.0f;
|
||||
hint_range[2] = 0.001f;
|
||||
}
|
||||
};
|
||||
|
||||
Map<StringName, Constant> constants;
|
||||
Map<StringName, Varying> varyings;
|
||||
Map<StringName, Uniform> uniforms;
|
||||
Map<StringName, Struct> structs;
|
||||
Vector<StringName> render_modes;
|
||||
|
||||
Vector<Function> functions;
|
||||
Vector<Struct> vstructs;
|
||||
|
||||
ShaderNode() :
|
||||
Node(TYPE_SHADER) {}
|
||||
};
|
||||
|
||||
struct Expression {
|
||||
bool is_op;
|
||||
union {
|
||||
Operator op;
|
||||
Node *node;
|
||||
};
|
||||
};
|
||||
|
||||
struct VarInfo {
|
||||
StringName name;
|
||||
DataType type;
|
||||
};
|
||||
|
||||
enum CompletionType {
|
||||
COMPLETION_NONE,
|
||||
COMPLETION_RENDER_MODE,
|
||||
COMPLETION_MAIN_FUNCTION,
|
||||
COMPLETION_IDENTIFIER,
|
||||
COMPLETION_FUNCTION_CALL,
|
||||
COMPLETION_CALL_ARGUMENTS,
|
||||
COMPLETION_INDEX,
|
||||
COMPLETION_STRUCT,
|
||||
};
|
||||
|
||||
struct Token {
|
||||
TokenType type;
|
||||
StringName text;
|
||||
double constant;
|
||||
uint16_t line;
|
||||
};
|
||||
|
||||
static String get_operator_text(Operator p_op);
|
||||
static String get_token_text(Token p_token);
|
||||
|
||||
static bool is_token_datatype(TokenType p_type);
|
||||
static bool is_token_variable_datatype(TokenType p_type);
|
||||
static DataType get_token_datatype(TokenType p_type);
|
||||
static bool is_token_interpolation(TokenType p_type);
|
||||
static DataInterpolation get_token_interpolation(TokenType p_type);
|
||||
static bool is_token_precision(TokenType p_type);
|
||||
static DataPrecision get_token_precision(TokenType p_type);
|
||||
static String get_precision_name(DataPrecision p_type);
|
||||
static String get_datatype_name(DataType p_type);
|
||||
static bool is_token_nonvoid_datatype(TokenType p_type);
|
||||
static bool is_token_operator(TokenType p_type);
|
||||
|
||||
static bool convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value = NULL);
|
||||
static DataType get_scalar_type(DataType p_type);
|
||||
static int get_cardinality(DataType p_type);
|
||||
static bool is_scalar_type(DataType p_type);
|
||||
static bool is_sampler_type(DataType p_type);
|
||||
static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint = ShaderLanguage::ShaderNode::Uniform::HINT_NONE);
|
||||
static PropertyInfo uniform_to_property_info(const ShaderNode::Uniform &p_uniform);
|
||||
static uint32_t get_type_size(DataType p_type);
|
||||
|
||||
static void get_keyword_list(List<String> *r_keywords);
|
||||
static void get_builtin_funcs(List<String> *r_keywords);
|
||||
|
||||
struct BuiltInInfo {
|
||||
DataType type;
|
||||
bool constant;
|
||||
|
||||
BuiltInInfo() :
|
||||
type(TYPE_VOID),
|
||||
constant(false) {}
|
||||
|
||||
BuiltInInfo(DataType p_type, bool p_constant = false) :
|
||||
type(p_type),
|
||||
constant(p_constant) {}
|
||||
};
|
||||
|
||||
struct FunctionInfo {
|
||||
Map<StringName, BuiltInInfo> built_ins;
|
||||
bool can_discard;
|
||||
};
|
||||
static bool has_builtin(const Map<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name);
|
||||
|
||||
private:
|
||||
struct KeyWord {
|
||||
TokenType token;
|
||||
const char *text;
|
||||
};
|
||||
|
||||
static const KeyWord keyword_list[];
|
||||
|
||||
bool error_set;
|
||||
String error_str;
|
||||
int error_line;
|
||||
|
||||
String code;
|
||||
int char_idx;
|
||||
int tk_line;
|
||||
|
||||
StringName current_function;
|
||||
|
||||
struct TkPos {
|
||||
int char_idx;
|
||||
int tk_line;
|
||||
};
|
||||
|
||||
TkPos _get_tkpos() {
|
||||
TkPos tkp;
|
||||
tkp.char_idx = char_idx;
|
||||
tkp.tk_line = tk_line;
|
||||
return tkp;
|
||||
}
|
||||
|
||||
void _set_tkpos(TkPos p_pos) {
|
||||
char_idx = p_pos.char_idx;
|
||||
tk_line = p_pos.tk_line;
|
||||
}
|
||||
|
||||
void _set_error(const String &p_str) {
|
||||
if (error_set)
|
||||
return;
|
||||
|
||||
error_line = tk_line;
|
||||
error_set = true;
|
||||
error_str = p_str;
|
||||
}
|
||||
|
||||
static const char *token_names[TK_MAX];
|
||||
|
||||
Token _make_token(TokenType p_type, const StringName &p_text = StringName());
|
||||
Token _get_token();
|
||||
|
||||
ShaderNode *shader;
|
||||
|
||||
enum IdentifierType {
|
||||
IDENTIFIER_FUNCTION,
|
||||
IDENTIFIER_UNIFORM,
|
||||
IDENTIFIER_VARYING,
|
||||
IDENTIFIER_FUNCTION_ARGUMENT,
|
||||
IDENTIFIER_LOCAL_VAR,
|
||||
IDENTIFIER_BUILTIN_VAR,
|
||||
IDENTIFIER_CONSTANT,
|
||||
};
|
||||
|
||||
bool _find_identifier(const BlockNode *p_block, bool p_allow_reassign, const Map<StringName, BuiltInInfo> &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL, bool *r_is_const = NULL, int *r_array_size = NULL, StringName *r_struct_name = NULL);
|
||||
bool _is_operator_assign(Operator p_op) const;
|
||||
bool _validate_assign(Node *p_node, const Map<StringName, BuiltInInfo> &p_builtin_types, String *r_message = NULL);
|
||||
bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL);
|
||||
|
||||
struct BuiltinFuncDef {
|
||||
enum { MAX_ARGS = 5 };
|
||||
const char *name;
|
||||
DataType rettype;
|
||||
const DataType args[MAX_ARGS];
|
||||
SubClassTag tag;
|
||||
bool high_end;
|
||||
};
|
||||
|
||||
struct BuiltinFuncOutArgs { //arguments used as out in built in functions
|
||||
const char *name;
|
||||
int argument;
|
||||
};
|
||||
|
||||
CompletionType completion_type;
|
||||
int completion_line;
|
||||
BlockNode *completion_block;
|
||||
DataType completion_base;
|
||||
SubClassTag completion_class;
|
||||
StringName completion_function;
|
||||
StringName completion_struct;
|
||||
int completion_argument;
|
||||
|
||||
bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier);
|
||||
static const BuiltinFuncDef builtin_func_defs[];
|
||||
static const BuiltinFuncOutArgs builtin_func_out_args[];
|
||||
|
||||
Error _validate_datatype(DataType p_type);
|
||||
bool _compare_datatypes_in_nodes(Node *a, Node *b) const;
|
||||
|
||||
bool _validate_function_call(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str);
|
||||
bool _parse_function_arguments(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL);
|
||||
bool _propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat);
|
||||
bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin);
|
||||
|
||||
Node *_parse_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
|
||||
ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node);
|
||||
|
||||
Node *_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types);
|
||||
Error _parse_block(BlockNode *p_block, const Map<StringName, BuiltInInfo> &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false);
|
||||
String _get_shader_type_list(const Set<String> &p_shader_types) const;
|
||||
String _get_qualifier_str(ArgumentQualifier p_qualifier) const;
|
||||
|
||||
Error _parse_shader(const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types);
|
||||
|
||||
Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op);
|
||||
Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op);
|
||||
|
||||
public:
|
||||
//static void get_keyword_list(ShaderType p_type,List<String> *p_keywords);
|
||||
|
||||
void clear();
|
||||
|
||||
static String get_shader_type(const String &p_code);
|
||||
Error compile(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types);
|
||||
Error complete(const String &p_code, const Map<StringName, FunctionInfo> &p_functions, const Vector<StringName> &p_render_modes, const Set<String> &p_shader_types, List<ScriptCodeCompletionOption> *r_options, String &r_call_hint);
|
||||
|
||||
String get_error_text();
|
||||
int get_error_line();
|
||||
|
||||
ShaderNode *get_shader();
|
||||
|
||||
String token_debug(const String &p_code);
|
||||
|
||||
ShaderLanguage();
|
||||
~ShaderLanguage();
|
||||
};
|
||||
|
||||
#endif // SHADER_LANGUAGE_H
|
||||
328
servers/rendering/shader_types.cpp
Normal file
328
servers/rendering/shader_types.cpp
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
/*************************************************************************/
|
||||
/* shader_types.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "shader_types.h"
|
||||
|
||||
const Map<StringName, ShaderLanguage::FunctionInfo> &ShaderTypes::get_functions(RS::ShaderMode p_mode) {
|
||||
|
||||
return shader_modes[p_mode].functions;
|
||||
}
|
||||
|
||||
const Vector<StringName> &ShaderTypes::get_modes(RS::ShaderMode p_mode) {
|
||||
|
||||
return shader_modes[p_mode].modes;
|
||||
}
|
||||
|
||||
const Set<String> &ShaderTypes::get_types() {
|
||||
return shader_types;
|
||||
}
|
||||
|
||||
ShaderTypes *ShaderTypes::singleton = NULL;
|
||||
|
||||
static ShaderLanguage::BuiltInInfo constt(ShaderLanguage::DataType p_type) {
|
||||
|
||||
return ShaderLanguage::BuiltInInfo(p_type, true);
|
||||
}
|
||||
|
||||
ShaderTypes::ShaderTypes() {
|
||||
singleton = this;
|
||||
|
||||
/*************** SPATIAL ***********************/
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["BINORMAL"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["POSITION"] = ShaderLanguage::TYPE_VEC4;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["UV2"] = ShaderLanguage::TYPE_VEC2;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_ID"] = constt(ShaderLanguage::TYPE_INT);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].can_discard = false;
|
||||
|
||||
//builtins
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VERTEX"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["FRONT_FACING"] = constt(ShaderLanguage::TYPE_BOOL);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["BINORMAL"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["UV2"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["METALLIC"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SPECULAR"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["RIM"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["RIM_TINT"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CLEARCOAT"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CLEARCOAT_GLOSS"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY_FLOW"] = ShaderLanguage::TYPE_VEC2;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_STRENGTH"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["TRANSMISSION"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO_LIGHT_AFFECT"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_NORMAL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT3);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].can_discard = true;
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["UV2"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["TRANSMISSION"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["DIFFUSE_LIGHT"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["SPECULAR_LIGHT"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT;
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].functions["light"].can_discard = true;
|
||||
|
||||
//order used puts first enum mode (default) first
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_mix");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_add");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_sub");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_mul");
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_opaque");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_always");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_never");
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_prepass_alpha");
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_test_disabled");
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_back");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_front");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_disabled");
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("unshaded");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("wireframe");
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert_wrap");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_oren_nayar");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_burley");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_toon");
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_schlick_ggx");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_blinn");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_phong");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_toon");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_disabled");
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("skip_vertex_transform");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("world_vertex_coords");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("ensure_correct_normals");
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("shadows_disabled");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("ambient_light_disabled");
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("shadow_to_opacity");
|
||||
|
||||
shader_modes[RS::SHADER_SPATIAL].modes.push_back("vertex_lighting");
|
||||
|
||||
/************ CANVAS ITEM **************************/
|
||||
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT;
|
||||
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CANVAS_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["SCREEN_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].can_discard = false;
|
||||
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SHADOW_VERTEX"] = ShaderLanguage::TYPE_VEC2;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["LIGHT_VERTEX"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SPECULAR_SHININESS_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SPECULAR_SHININESS"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true;
|
||||
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SPECULAR_SHININESS"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_VERTEX"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC4;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SHADOW_MODULATE"] = ShaderLanguage::TYPE_VEC4;
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].can_discard = true;
|
||||
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("skip_vertex_transform");
|
||||
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_mix");
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_add");
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_sub");
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_mul");
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_premul_alpha");
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_disabled");
|
||||
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("unshaded");
|
||||
shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("light_only");
|
||||
|
||||
/************ PARTICLES **************************/
|
||||
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["VELOCITY"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["MASS"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["ACTIVE"] = ShaderLanguage::TYPE_BOOL;
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["RESTART"] = constt(ShaderLanguage::TYPE_BOOL);
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["CUSTOM"] = ShaderLanguage::TYPE_VEC4;
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["TRANSFORM"] = ShaderLanguage::TYPE_MAT4;
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["LIFETIME"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["DELTA"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT);
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_INT);
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4);
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT);
|
||||
shader_modes[RS::SHADER_PARTICLES].functions["vertex"].can_discard = false;
|
||||
|
||||
shader_modes[RS::SHADER_PARTICLES].modes.push_back("disable_force");
|
||||
shader_modes[RS::SHADER_PARTICLES].modes.push_back("disable_velocity");
|
||||
shader_modes[RS::SHADER_PARTICLES].modes.push_back("keep_data");
|
||||
|
||||
/************ SKY **************************/
|
||||
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["RADIANCE"] = constt(ShaderLanguage::TYPE_SAMPLERCUBE);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["AT_HALF_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["AT_QUARTER_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["AT_CUBEMAP_PASS"] = constt(ShaderLanguage::TYPE_BOOL);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT0_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT0_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT0_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT0_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT1_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT1_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT1_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT1_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT2_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT2_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT2_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT2_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_COLOR"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
|
||||
shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT;
|
||||
shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["EYEDIR"] = constt(ShaderLanguage::TYPE_VEC3);
|
||||
shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["SKY_COORDS"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["HALF_RES_COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["QUARTER_RES_COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
|
||||
shader_modes[RS::SHADER_SKY].modes.push_back("use_half_res_pass");
|
||||
shader_modes[RS::SHADER_SKY].modes.push_back("use_quarter_res_pass");
|
||||
|
||||
shader_types.insert("spatial");
|
||||
shader_types.insert("canvas_item");
|
||||
shader_types.insert("particles");
|
||||
shader_types.insert("sky");
|
||||
}
|
||||
62
servers/rendering/shader_types.h
Normal file
62
servers/rendering/shader_types.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*************************************************************************/
|
||||
/* shader_types.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef SHADERTYPES_H
|
||||
#define SHADERTYPES_H
|
||||
|
||||
#include "core/ordered_hash_map.h"
|
||||
#include "servers/rendering_server.h"
|
||||
#include "shader_language.h"
|
||||
|
||||
class ShaderTypes {
|
||||
|
||||
struct Type {
|
||||
|
||||
Map<StringName, ShaderLanguage::FunctionInfo> functions;
|
||||
Vector<StringName> modes;
|
||||
};
|
||||
|
||||
Map<RS::ShaderMode, Type> shader_modes;
|
||||
|
||||
static ShaderTypes *singleton;
|
||||
|
||||
Set<String> shader_types;
|
||||
|
||||
public:
|
||||
static ShaderTypes *get_singleton() { return singleton; }
|
||||
|
||||
const Map<StringName, ShaderLanguage::FunctionInfo> &get_functions(RS::ShaderMode p_mode);
|
||||
const Vector<StringName> &get_modes(RS::ShaderMode p_mode);
|
||||
const Set<String> &get_types();
|
||||
|
||||
ShaderTypes();
|
||||
};
|
||||
|
||||
#endif // SHADERTYPES_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue