all light types and shadows are working, pending a lot of clean-up

This commit is contained in:
Juan Linietsky 2016-11-09 23:55:06 -03:00
parent 6b2a27bbe5
commit cacf9ebb7f
38 changed files with 3241 additions and 418 deletions

View file

@ -495,6 +495,28 @@ void CameraMatrix::set_light_bias() {
}
void CameraMatrix::set_light_atlas_rect(const Rect2& p_rect) {
float *m=&matrix[0][0];
m[0]=p_rect.size.width,
m[1]=0.0,
m[2]=0.0,
m[3]=0.0,
m[4]=0.0,
m[5]=p_rect.size.height,
m[6]=0.0,
m[7]=0.0,
m[8]=0.0,
m[9]=0.0,
m[10]=1.0,
m[11]=0.0,
m[12]=p_rect.pos.x,
m[13]=p_rect.pos.y,
m[14]=0.0,
m[15]=1.0;
}
CameraMatrix::operator String() const {
String str;

View file

@ -30,6 +30,7 @@
#define CAMERA_MATRIX_H
#include "transform.h"
#include "math_2d.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@ -53,6 +54,7 @@ struct CameraMatrix {
void set_identity();
void set_zero();
void set_light_bias();
void set_light_atlas_rect(const Rect2& p_rect);
void set_perspective(float p_fovy_degrees, float p_aspect, float p_z_near, float p_z_far,bool p_flip_fov=false);
void set_orthogonal(float p_left, float p_right, float p_bottom, float p_top, float p_znear, float p_zfar);
void set_orthogonal(float p_size, float p_aspect, float p_znear, float p_zfar,bool p_flip_fov=false);

View file

@ -208,7 +208,7 @@ public:
}
}
static _FORCE_INLINE_ float halfptr_to_float(uint16_t *h) {
static _FORCE_INLINE_ float halfptr_to_float(const uint16_t *h) {
union {
uint32_t u32;

View file

@ -824,8 +824,6 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const
bool prev_distance_field=false;
while(p_item_list) {
Item *ci=p_item_list;

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,7 @@
#include "rasterizer_storage_gles3.h"
#include "drivers/gles3/shaders/scene.glsl.h"
#include "drivers/gles3/shaders/cube_to_dp.glsl.h"
class RasterizerSceneGLES3 : public RasterizerScene {
public:
@ -16,10 +17,13 @@ public:
uint32_t current_geometry_index;
RID default_material;
RID default_material_twosided;
RID default_shader;
RID default_shader_twosided;
RasterizerStorageGLES3 *storage;
struct State {
@ -29,6 +33,7 @@ public:
int current_depth_draw;
SceneShaderGLES3 scene_shader;
CubeToDpShaderGLES3 cube_to_dp_shader;
struct SceneDataUBO {
@ -41,6 +46,12 @@ public:
float bg_color[4];
float ambient_energy;
float bg_energy;
float shadow_z_offset;
float shadow_slope_scale;
float shadow_dual_paraboloid_render_zfar;
float shadow_dual_paraboloid_render_side;
float shadow_atlas_pixel_size[2];
float shadow_directional_pixel_size[2];
} ubo_data;
@ -62,7 +73,7 @@ public:
GLuint skybox_verts;
GLuint skybox_array;
bool cull_front;
} state;
@ -71,7 +82,6 @@ public:
struct ShadowAtlas : public RID_Data {
enum {
SHADOW_INDEX_DIRTY_BIT=(1<<31),
QUADRANT_SHIFT=27,
SHADOW_INDEX_MASK=(1<<QUADRANT_SHIFT)-1,
SHADOW_INVALID=0xFFFFFFFF
@ -111,13 +121,35 @@ public:
Map<RID,uint32_t> shadow_owners;
};
struct ShadowCubeMap {
GLuint fbo_id[6];
GLuint cubemap;
int size;
};
Vector<ShadowCubeMap> shadow_cubemaps;
RID_Owner<ShadowAtlas> shadow_atlas_owner;
RID shadow_atlas_create();
void shadow_atlas_set_size(RID p_atlas,int p_size);
void shadow_atlas_set_quadrant_subdivision(RID p_atlas,int p_quadrant,int p_subdivision);
bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
uint32_t shadow_atlas_update_light(RID p_atlas,RID p_light_intance,float p_coverage,uint64_t p_light_version);
bool shadow_atlas_update_light(RID p_atlas,RID p_light_intance,float p_coverage,uint64_t p_light_version);
struct DirectionalShadow {
GLuint fbo;
GLuint depth;
int light_count;
int size;
int current_light;
} directional_shadow;
virtual int get_directional_light_shadow_size(RID p_light_intance);
virtual void set_directional_shadow_count(int p_count);
/* ENVIRONMENT API */
@ -174,12 +206,12 @@ public:
struct LightInstance : public RID_Data {
struct SplitInfo {
struct ShadowTransform {
CameraMatrix camera;
Transform transform;
float near;
float far;
float split;
};
struct LightDataUBO {
@ -188,6 +220,7 @@ public:
float light_direction_attenuation[4];
float light_color_energy[4];
float light_params[4]; //cone attenuation, specular, shadow darkening,
float light_clamp[4]; //cone attenuation, specular, shadow darkening,
float shadow_split_offsets[4];
float shadow_matrix1[16];
float shadow_matrix2[16];
@ -197,13 +230,11 @@ public:
} light_ubo_data;
SplitInfo split_info[4];
ShadowTransform shadow_transform[4];
RID self;
RID light;
RasterizerStorageGLES3::Light *light_ptr;
CameraMatrix shadow_matrix[4];
Transform transform;
Vector3 light_vector;
@ -214,12 +245,17 @@ public:
uint64_t shadow_pass;
uint64_t last_scene_pass;
uint64_t last_scene_shadow_pass;
uint64_t last_pass;
uint16_t light_index;
uint16_t light_directional_index;
uint32_t current_shadow_atlas_key;
Vector2 dp;
CameraMatrix shadow_projection[4];
Rect2 directional_rect;
Set<RID> shadow_atlases; //shadow atlases where this light is registered
@ -231,6 +267,7 @@ public:
virtual RID light_instance_create(RID p_light);
virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform);
virtual void light_instance_set_shadow_transform(RID p_light_instance,const CameraMatrix& p_projection,const Transform& p_transform,float p_far,float p_split,int p_pass);
virtual void light_instance_mark_visible(RID p_light_instance);
/* RENDER LIST */
@ -371,26 +408,31 @@ public:
RenderList render_list;
_FORCE_INLINE_ void _set_cull(bool p_front,bool p_reverse_cull);
_FORCE_INLINE_ bool _setup_material(RasterizerStorageGLES3::Material* p_material,bool p_alpha_pass);
_FORCE_INLINE_ void _setup_transform(InstanceBase *p_instance,const Transform& p_view_transform,const CameraMatrix& p_projection);
_FORCE_INLINE_ void _setup_geometry(RenderList::Element *e);
_FORCE_INLINE_ void _render_geometry(RenderList::Element *e);
_FORCE_INLINE_ void _setup_light(LightInstance *p_light);
void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, RasterizerStorageGLES3::Texture *p_base_env, bool p_reverse_cull, bool p_alpha_pass);
void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, RasterizerStorageGLES3::Texture *p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow);
_FORCE_INLINE_ void _add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material);
_FORCE_INLINE_ void _add_geometry( RasterizerStorageGLES3::Geometry* p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner,int p_material,bool p_shadow);
void _draw_skybox(RID p_skybox, CameraMatrix& p_projection, const Transform& p_transform, bool p_vflip, float p_scale);
void _draw_skybox(RID p_skybox, const CameraMatrix& p_projection, const Transform& p_transform, bool p_vflip, float p_scale);
void _setup_environment(Environment *env,CameraMatrix& p_cam_projection, const Transform& p_cam_transform);
void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform,const CameraMatrix& p_camera_projection);
void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform& p_cam_transform);
void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix& p_camera_projection, RID p_shadow_atlas);
void _copy_screen();
void _copy_to_front_buffer(Environment *env);
void _copy_texture_to_front_buffer(GLuint p_texture); //used for debug
virtual void render_scene(const Transform& p_cam_transform,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_directional_lights,int p_directional_light_count,RID p_environment);
void _fill_render_list(InstanceBase** p_cull_result,int p_cull_count,bool p_shadow);
virtual void render_scene(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_environment,RID p_shadow_atlas);
virtual void render_shadow(RID p_light,RID p_shadow_atlas,int p_pass,InstanceBase** p_cull_result,int p_cull_count);
virtual bool free(RID p_rid);
void _generate_brdf();

View file

@ -1290,12 +1290,13 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const {
shaders.actions_scene.render_mode_values["cull_front"]=Pair<int*,int>(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_FRONT);
shaders.actions_scene.render_mode_values["cull_back"]=Pair<int*,int>(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_BACK);
shaders.actions_scene.render_mode_values["cull_disable"]=Pair<int*,int>(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_DISABLED);
shaders.actions_scene.render_mode_values["cull_disabled"]=Pair<int*,int>(&p_shader->spatial.cull_mode,Shader::Spatial::CULL_MODE_DISABLED);
shaders.actions_scene.render_mode_flags["unshaded"]=&p_shader->spatial.unshaded;
shaders.actions_scene.render_mode_flags["ontop"]=&p_shader->spatial.ontop;
shaders.actions_scene.usage_flag_pointers["ALPHA"]=&p_shader->spatial.uses_alpha;
shaders.actions_scene.usage_flag_pointers["VERTEX"]=&p_shader->spatial.uses_vertex;
actions=&shaders.actions_scene;
actions->uniforms=&p_shader->uniforms;
@ -1318,6 +1319,9 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const {
p_shader->texture_count=gen_code.texture_uniforms.size();
p_shader->texture_hints=gen_code.texture_hints;
p_shader->uses_vertex_time=gen_code.uses_vertex_time;
p_shader->uses_fragment_time=gen_code.uses_fragment_time;
//all materials using this shader will have to be invalidated, unfortunately
for (SelfList<Material>* E = p_shader->materials.first();E;E=E->next() ) {
@ -1535,6 +1539,57 @@ void RasterizerStorageGLES3::material_set_line_width(RID p_material, float p_wid
}
bool RasterizerStorageGLES3::material_is_animated(RID p_material) {
Material *material = material_owner.get( p_material );
ERR_FAIL_COND_V(!material,false);
if (material->dirty_list.in_list()) {
_update_material(material);
}
return material->is_animated_cache;
}
bool RasterizerStorageGLES3::material_casts_shadows(RID p_material) {
Material *material = material_owner.get( p_material );
ERR_FAIL_COND_V(!material,false);
if (material->dirty_list.in_list()) {
_update_material(material);
}
return material->can_cast_shadow_cache;
}
void RasterizerStorageGLES3::material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) {
Material *material = material_owner.get( p_material );
ERR_FAIL_COND(!material);
Map<RasterizerScene::InstanceBase*,int>::Element *E=material->instance_owners.find(p_instance);
if (E) {
E->get()++;
} else {
material->instance_owners[p_instance]=1;
}
}
void RasterizerStorageGLES3::material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) {
Material *material = material_owner.get( p_material );
ERR_FAIL_COND(!material);
Map<RasterizerScene::InstanceBase*,int>::Element *E=material->instance_owners.find(p_instance);
ERR_FAIL_COND(!E);
E->get()--;
if (E->get()==0) {
material->instance_owners.erase(E);
}
}
_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant& value, uint8_t *data,bool p_linear_color) {
switch(type) {
case ShaderLanguage::TYPE_BOOL: {
@ -2011,6 +2066,48 @@ void RasterizerStorageGLES3::_update_material(Material* material) {
if (material->dirty_list.in_list())
_material_dirty_list.remove( &material->dirty_list );
if (material->shader && material->shader->dirty_list.in_list()) {
_update_shader(material->shader);
}
//update caches
{
bool can_cast_shadow = false;
bool is_animated = false;
if (material->shader && material->shader->mode==VS::SHADER_SPATIAL) {
if (!material->shader->spatial.uses_alpha && material->shader->spatial.blend_mode==Shader::Spatial::BLEND_MODE_MIX) {
can_cast_shadow=true;
}
if (material->shader->spatial.uses_discard && material->shader->uses_fragment_time) {
is_animated=true;
}
if (material->shader->spatial.uses_vertex && material->shader->uses_vertex_time) {
is_animated=true;
}
}
if (can_cast_shadow!=material->can_cast_shadow_cache || is_animated!=material->is_animated_cache) {
material->can_cast_shadow_cache=can_cast_shadow;
material->is_animated_cache=is_animated;
for(Map<Instantiable*,int>::Element *E=material->instantiable_owners.front();E;E=E->next()) {
E->key()->instance_material_change_notify();
}
for(Map<RasterizerScene::InstanceBase*,int>::Element *E=material->instance_owners.front();E;E=E->next()) {
E->key()->base_material_changed();
}
}
}
//clear ubo if it needs to be cleared
if (material->ubo_size) {
@ -2102,6 +2199,36 @@ void RasterizerStorageGLES3::_update_material(Material* material) {
}
void RasterizerStorageGLES3::_material_add_instantiable(RID p_material,Instantiable *p_instantiable) {
Material * material = material_owner.getornull(p_material);
ERR_FAIL_COND(!material);
Map<Instantiable*,int>::Element *I = material->instantiable_owners.find(p_instantiable);
if (I) {
I->get()++;
} else {
material->instantiable_owners[p_instantiable]=1;
}
}
void RasterizerStorageGLES3::_material_remove_instantiable(RID p_material,Instantiable *p_instantiable) {
Material * material = material_owner.getornull(p_material);
ERR_FAIL_COND(!material);
Map<Instantiable*,int>::Element *I = material->instantiable_owners.find(p_instantiable);
ERR_FAIL_COND(!I);
I->get()--;
if (I->get()==0) {
material->instantiable_owners.erase(I);
}
}
void RasterizerStorageGLES3::update_dirty_materials() {
while( _material_dirty_list.first() ) {
@ -2406,6 +2533,8 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P
surface->active=true;
surface->array_len=p_vertex_count;
surface->index_array_len=p_index_count;
surface->array_byte_size=p_array.size();
surface->index_array_byte_size=p_index_array.size();
surface->primitive=p_primitive;
surface->mesh=mesh;
surface->format=p_format;
@ -2556,8 +2685,22 @@ void RasterizerStorageGLES3::mesh_surface_set_material(RID p_mesh, int p_surface
ERR_FAIL_COND(!mesh);
ERR_FAIL_INDEX(p_surface,mesh->surfaces.size());
if (mesh->surfaces[p_surface]->material==p_material)
return;
if (mesh->surfaces[p_surface]->material.is_valid()) {
_material_remove_instantiable(mesh->surfaces[p_surface]->material,mesh);
}
mesh->surfaces[p_surface]->material=p_material;
if (mesh->surfaces[p_surface]->material.is_valid()) {
_material_add_instantiable(mesh->surfaces[p_surface]->material,mesh);
}
mesh->instance_material_change_notify();
}
RID RasterizerStorageGLES3::mesh_surface_get_material(RID p_mesh, int p_surface) const{
@ -2595,17 +2738,17 @@ DVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_array(RID p_mesh, int
Surface *surface = mesh->surfaces[p_surface];
glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id);
void * data = glMapBufferRange(GL_ARRAY_BUFFER,0,surface->array_len,GL_MAP_READ_BIT);
void * data = glMapBufferRange(GL_ARRAY_BUFFER,0,surface->array_byte_size,GL_MAP_READ_BIT);
ERR_FAIL_COND_V(!data,DVector<uint8_t>());
DVector<uint8_t> ret;
ret.resize(surface->array_len);
ret.resize(surface->array_byte_size);
{
DVector<uint8_t>::Write w = ret.write();
copymem(w.ptr(),data,surface->array_len);
copymem(w.ptr(),data,surface->array_byte_size);
}
glUnmapBuffer(GL_ARRAY_BUFFER);
@ -2622,18 +2765,18 @@ DVector<uint8_t> RasterizerStorageGLES3::mesh_surface_get_index_array(RID p_mesh
ERR_FAIL_COND_V(surface->index_array_len==0,DVector<uint8_t>());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->vertex_id);
void * data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER,0,surface->index_array_len,GL_MAP_READ_BIT);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,surface->index_id);
void * data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER,0,surface->index_array_byte_size,GL_MAP_READ_BIT);
ERR_FAIL_COND_V(!data,DVector<uint8_t>());
DVector<uint8_t> ret;
ret.resize(surface->index_array_len);
ret.resize(surface->index_array_byte_size);
{
DVector<uint8_t>::Write w = ret.write();
copymem(w.ptr(),data,surface->index_array_len);
copymem(w.ptr(),data,surface->index_array_byte_size);
}
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
@ -2662,6 +2805,59 @@ VS::PrimitiveType RasterizerStorageGLES3::mesh_surface_get_primitive_type(RID p_
return mesh->surfaces[p_surface]->primitive;
}
AABB RasterizerStorageGLES3::mesh_surface_get_aabb(RID p_mesh, int p_surface) const {
const Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND_V(!mesh,AABB());
ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),AABB());
return mesh->surfaces[p_surface]->aabb;
}
Vector<DVector<uint8_t> > RasterizerStorageGLES3::mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const{
const Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND_V(!mesh,Vector<DVector<uint8_t> >());
ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),Vector<DVector<uint8_t> >());
Vector<DVector<uint8_t> > bsarr;
for(int i=0;i<mesh->surfaces[p_surface]->morph_targets.size();i++) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,mesh->surfaces[p_surface]->morph_targets[i].vertex_id);
void * data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER,0,mesh->surfaces[p_surface]->array_byte_size,GL_MAP_READ_BIT);
ERR_FAIL_COND_V(!data,Vector<DVector<uint8_t> >());
DVector<uint8_t> ret;
ret.resize(mesh->surfaces[p_surface]->array_byte_size);
{
DVector<uint8_t>::Write w = ret.write();
copymem(w.ptr(),data,mesh->surfaces[p_surface]->array_byte_size);
}
bsarr.push_back(ret);
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
}
return bsarr;
}
Vector<AABB> RasterizerStorageGLES3::mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const{
const Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND_V(!mesh,Vector<AABB >());
ERR_FAIL_INDEX_V(p_surface,mesh->surfaces.size(),Vector<AABB >());
return mesh->surfaces[p_surface]->skeleton_bone_aabb;
}
void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){
Mesh *mesh = mesh_owner.getornull(p_mesh);
@ -2670,6 +2866,10 @@ void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){
Surface *surface = mesh->surfaces[p_surface];
if (surface->material.is_valid()) {
_material_remove_instantiable(surface->material,mesh);
}
glDeleteBuffers(1,&surface->vertex_id);
if (surface->index_id) {
glDeleteBuffers(1,&surface->index_id);
@ -2683,6 +2883,8 @@ void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){
glDeleteVertexArrays(1,&surface->morph_targets[i].array_id);
}
mesh->instance_material_change_notify();
memdelete(surface);
mesh->surfaces.remove(p_surface);
@ -2971,7 +3173,6 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type){
light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET]=0.1;
light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET]=0.3;
light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET]=0.6;
light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_4_OFFSET]=1.0;
light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS]=0.1;
light->param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE]=0.1;
@ -2981,6 +3182,10 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type){
light->negative=false;
light->cull_mask=0xFFFFFFFF;
light->directional_shadow_mode=VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
light->omni_shadow_mode=VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
light->omni_shadow_detail=VS::LIGHT_OMNI_SHADOW_DETAIL_VERTICAL;
light->version=0;
return light_owner.make_rid(light);
}
@ -2998,9 +3203,23 @@ void RasterizerStorageGLES3::light_set_param(RID p_light,VS::LightParam p_param,
ERR_FAIL_COND(!light);
ERR_FAIL_INDEX(p_param,VS::LIGHT_PARAM_MAX);
if (p_param==VS::LIGHT_PARAM_RANGE || p_param==VS::LIGHT_PARAM_SPOT_ANGLE) {
light->instance_change_notify();
switch(p_param) {
case VS::LIGHT_PARAM_RANGE:
case VS::LIGHT_PARAM_SPOT_ANGLE:
case VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE:
case VS::LIGHT_PARAM_SHADOW_DARKNESS:
case VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET:
case VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET:
case VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET:
case VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS:
case VS::LIGHT_PARAM_SHADOW_BIAS:
case VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE: {
light->version++;
light->instance_change_notify();
} break;
}
light->param[p_param]=p_value;
}
void RasterizerStorageGLES3::light_set_shadow(RID p_light,bool p_enabled){
@ -3009,6 +3228,10 @@ void RasterizerStorageGLES3::light_set_shadow(RID p_light,bool p_enabled){
ERR_FAIL_COND(!light);
light->shadow=p_enabled;
light->version++;
light->instance_change_notify();
}
void RasterizerStorageGLES3::light_set_projector(RID p_light,RID p_texture){
@ -3021,9 +3244,8 @@ void RasterizerStorageGLES3::light_set_attenuation_texure(RID p_light,RID p_text
Light * light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
}
void RasterizerStorageGLES3::light_set_negative(RID p_light,bool p_enable){
Light * light = light_owner.getornull(p_light);
@ -3037,6 +3259,10 @@ void RasterizerStorageGLES3::light_set_cull_mask(RID p_light,uint32_t p_mask){
ERR_FAIL_COND(!light);
light->cull_mask=p_mask;
light->version++;
light->instance_change_notify();
}
void RasterizerStorageGLES3::light_set_shader(RID p_light,RID p_shader){
@ -3045,22 +3271,92 @@ void RasterizerStorageGLES3::light_set_shader(RID p_light,RID p_shader){
}
void RasterizerStorageGLES3::light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode) {
Light * light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->omni_shadow_mode=p_mode;
light->version++;
light->instance_change_notify();
}
VS::LightOmniShadowMode RasterizerStorageGLES3::light_omni_get_shadow_mode(RID p_light) {
const Light * light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light,VS::LIGHT_OMNI_SHADOW_CUBE);
return light->omni_shadow_mode;
}
void RasterizerStorageGLES3::light_omni_set_shadow_detail(RID p_light,VS::LightOmniShadowDetail p_detail) {
Light * light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->omni_shadow_detail=p_detail;
light->version++;
light->instance_change_notify();
}
void RasterizerStorageGLES3::light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode){
Light * light = light_owner.getornull(p_light);
ERR_FAIL_COND(!light);
light->directional_shadow_mode=p_mode;
light->version++;
light->instance_change_notify();
}
VS::LightDirectionalShadowMode RasterizerStorageGLES3::light_directional_get_shadow_mode(RID p_light) {
const Light * light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light,VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL);
return light->directional_shadow_mode;
}
VS::LightType RasterizerStorageGLES3::light_get_type(RID p_light) const {
const Light * light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light,VS::LIGHT_DIRECTIONAL);
return VS::LIGHT_DIRECTIONAL;
return light->type;
}
float RasterizerStorageGLES3::light_get_param(RID p_light,VS::LightParam p_param) {
const Light * light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light,VS::LIGHT_DIRECTIONAL);
return light->param[p_param];
}
bool RasterizerStorageGLES3::light_has_shadow(RID p_light) const {
const Light * light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light,VS::LIGHT_DIRECTIONAL);
return light->shadow;
}
uint64_t RasterizerStorageGLES3::light_get_version(RID p_light) const {
const Light * light = light_owner.getornull(p_light);
ERR_FAIL_COND_V(!light,0);
return light->version;
}
AABB RasterizerStorageGLES3::light_get_aabb(RID p_light) const {
const Light * light = light_owner.getornull(p_light);

View file

@ -99,6 +99,38 @@ public:
struct Instantiable : public RID_Data {
SelfList<RasterizerScene::InstanceBase>::List instance_list;
_FORCE_INLINE_ void instance_change_notify() {
SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first();
while(instances) {
instances->self()->base_changed();
instances=instances->next();
}
}
_FORCE_INLINE_ void instance_material_change_notify() {
SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first();
while(instances) {
instances->self()->base_material_changed();
instances=instances->next();
}
}
Instantiable() { }
virtual ~Instantiable() {
while(instance_list.first()) {
instance_list.first()->self()->base_removed();
}
}
};
@ -282,9 +314,14 @@ public:
bool uses_alpha;
bool unshaded;
bool ontop;
bool uses_vertex;
bool uses_discard;
} spatial;
bool uses_vertex_time;
bool uses_fragment_time;
Shader() : dirty_list(this) {
shader=NULL;
@ -315,6 +352,8 @@ public:
void update_dirty_shaders();
/* COMMON MATERIAL API */
struct Material : public RID_Data {
@ -331,7 +370,15 @@ public:
uint32_t index;
uint64_t last_pass;
Map<Instantiable*,int> instantiable_owners;
Map<RasterizerScene::InstanceBase*,int> instance_owners;
bool can_cast_shadow_cache;
bool is_animated_cache;
Material() : list(this), dirty_list(this) {
can_cast_shadow_cache=false;
is_animated_cache=false;
shader=NULL;
line_width=1.0;
ubo_id=0;
@ -343,6 +390,8 @@ public:
mutable SelfList<Material>::List _material_dirty_list;
void _material_make_dirty(Material *p_material) const;
void _material_add_instantiable(RID p_material,Instantiable *p_instantiable);
void _material_remove_instantiable(RID p_material, Instantiable *p_instantiable);
mutable RID_Owner<Material> material_owner;
@ -357,34 +406,18 @@ public:
virtual void material_set_line_width(RID p_material, float p_width);
virtual bool material_is_animated(RID p_material);
virtual bool material_casts_shadows(RID p_material);
virtual void material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance);
virtual void material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance);
void _update_material(Material* material);
void update_dirty_materials();
/* MESH API */
struct Instantiable : public RID_Data {
SelfList<RasterizerScene::InstanceBase>::List instance_list;
_FORCE_INLINE_ void instance_change_notify() {
SelfList<RasterizerScene::InstanceBase> *instances = instance_list.first();
while(instances) {
instances->self()->base_changed();
instances=instances->next();
}
}
Instantiable() { }
virtual ~Instantiable() {
while(instance_list.first()) {
instance_list.first()->self()->base_removed();
}
}
};
struct Geometry : Instantiable {
@ -455,7 +488,8 @@ public:
int index_array_len;
int max_bone;
int array_bytes;
int array_byte_size;
int index_array_byte_size;
VS::PrimitiveType primitive;
@ -464,7 +498,8 @@ public:
Surface() {
array_bytes=0;
array_byte_size=0;
index_array_byte_size=0;
mesh=NULL;
format=0;
array_id=0;
@ -526,6 +561,10 @@ public:
virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const;
virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const;
virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const;
virtual Vector<DVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const;
virtual Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const;
virtual void mesh_remove_surface(RID p_mesh, int p_surface);
virtual int mesh_get_surface_count(RID p_mesh) const;
@ -598,7 +637,10 @@ public:
bool shadow;
bool negative;
uint32_t cull_mask;
VS::LightOmniShadowMode omni_shadow_mode;
VS::LightOmniShadowDetail omni_shadow_detail;
VS::LightDirectionalShadowMode directional_shadow_mode;
uint64_t version;
};
mutable RID_Owner<Light> light_owner;
@ -614,11 +656,22 @@ public:
virtual void light_set_cull_mask(RID p_light,uint32_t p_mask);
virtual void light_set_shader(RID p_light,RID p_shader);
virtual void light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode);
virtual void light_omni_set_shadow_detail(RID p_light,VS::LightOmniShadowDetail p_detail);
virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode);
virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light);
virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light);
virtual bool light_has_shadow(RID p_light) const;
virtual VS::LightType light_get_type(RID p_light) const;
virtual float light_get_param(RID p_light,VS::LightParam p_param);
virtual AABB light_get_aabb(RID p_light) const;
virtual uint64_t light_get_version(RID p_light) const;
/* PROBE API */
virtual RID reflection_probe_create();

View file

@ -330,6 +330,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
SL::FunctionNode *fnode=pnode->functions[i].function;
current_func_name=fnode->name;
if (fnode->name=="vertex") {
@ -401,6 +402,14 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
else
code=_mkid(vnode->name);
if (vnode->name==time_name) {
if (current_func_name==vertex_name) {
r_gen_code.uses_vertex_time=true;
}
if (current_func_name==fragment_name) {
r_gen_code.uses_fragment_time=true;
}
}
} break;
case SL::Node::TYPE_CONSTANT: {
@ -536,6 +545,8 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String& p_code,
r_gen_code.fragment=String();
r_gen_code.fragment_global=String();
r_gen_code.light=String();
r_gen_code.uses_fragment_time=false;
r_gen_code.uses_vertex_time=false;
@ -645,7 +656,9 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
vertex_name="vertex";
fragment_name="fragment";
time_name="TIME";

View file

@ -32,6 +32,9 @@ public:
String fragment;
String light;
bool uses_fragment_time;
bool uses_vertex_time;
};
private:
@ -49,6 +52,10 @@ private:
String _dump_node_code(ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions& p_actions, const DefaultIdentifierActions& p_default_actions);
StringName current_func_name;
StringName vertex_name;
StringName fragment_name;
StringName time_name;
Set<StringName> used_name_defines;
Set<StringName> used_rmode_defines;

View file

@ -6,4 +6,5 @@ if env['BUILDERS'].has_key('GLES3_GLSL'):
env.GLES3_GLSL('canvas_shadow.glsl');
env.GLES3_GLSL('scene.glsl');
env.GLES3_GLSL('cubemap_filter.glsl');
env.GLES3_GLSL('cube_to_dp.glsl');

View file

@ -0,0 +1,79 @@
[vertex]
layout(location=0) in highp vec4 vertex_attrib;
layout(location=4) in vec2 uv_in;
out vec2 uv_interp;
void main() {
uv_interp = uv_in;
gl_Position = vertex_attrib;
}
[fragment]
uniform highp samplerCube source_cube; //texunit:0
in vec2 uv_interp;
uniform bool z_flip;
uniform highp float z_far;
uniform highp float z_near;
uniform highp float bias;
void main() {
highp vec3 normal = vec3( uv_interp * 2.0 - 1.0, 0.0 );
/*
if(z_flip) {
normal.z = 0.5 - 0.5*((normal.x * normal.x) + (normal.y * normal.y));
} else {
normal.z = -0.5 + 0.5*((normal.x * normal.x) + (normal.y * normal.y));
}
*/
//normal.z = sqrt(1.0-dot(normal.xy,normal.xy));
//normal.xy*=1.0+normal.z;
normal.z = 0.5 - 0.5*((normal.x * normal.x) + (normal.y * normal.y));
normal = normalize(normal);
/*
normal.z=0.5;
normal=normalize(normal);
*/
if (!z_flip) {
normal.z=-normal.z;
}
//normal = normalize(vec3( uv_interp * 2.0 - 1.0, 1.0 ));
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 * z_near * z_far / (z_far + z_near - depth * (z_far - z_near));
gl_FragDepth = (linear_depth*depth_fix+bias) / z_far;
}

View file

@ -1,7 +1,6 @@
[vertex]
#define ENABLE_UV_INTERP
/*
from VisualServer:
@ -56,6 +55,15 @@ layout(std140) uniform SceneData { //ubo:0
highp vec4 bg_color;
float ambient_energy;
float bg_energy;
float shadow_z_offset;
float shadow_z_slope_scale;
float shadow_dual_paraboloid_render_zfar;
float shadow_dual_paraboloid_render_side;
vec2 shadow_atlas_pixel_size;
vec2 directional_shadow_pixel_size;
};
uniform highp mat4 world_transform;
@ -68,6 +76,7 @@ layout(std140) uniform LightData { //ubo:3
mediump vec4 light_direction_attenuation;
mediump vec4 light_color_energy;
mediump vec4 light_params; //cone attenuation, specular, shadow darkening,
mediump vec4 light_clamp;
mediump vec4 shadow_split_offsets;
highp mat4 shadow_matrix1;
highp mat4 shadow_matrix2;
@ -75,19 +84,6 @@ layout(std140) uniform LightData { //ubo:3
highp mat4 shadow_matrix4;
};
#ifdef USE_FORWARD_1_SHADOW_MAP
out mediump vec4 forward_shadow_pos1;
#endif
#ifdef USE_FORWARD_2_SHADOW_MAP
out mediump vec4 forward_shadow_pos2;
#endif
#ifdef USE_FORWARD_4_SHADOW_MAP
out mediump vec4 forward_shadow_pos3;
out mediump vec4 forward_shadow_pos4;
#endif
#endif
/* Varyings */
@ -120,13 +116,6 @@ varying vec4 position_interp;
#endif
#ifdef USE_SHADOW_PASS
uniform highp float shadow_z_offset;
uniform highp float shadow_z_slope_scale;
#endif
VERTEX_SHADER_GLOBALS
@ -141,6 +130,11 @@ MATERIAL_UNIFORMS
#endif
#ifdef RENDER_SHADOW_DUAL_PARABOLOID
out highp float dp_clip;
#endif
void main() {
@ -206,15 +200,6 @@ VERTEX_SHADER_CODE
}
#ifdef USE_SHADOW_PASS
float z_ofs = shadow_z_offset;
z_ofs += (1.0-abs(normal_interp.z))*shadow_z_slope_scale;
vertex_interp.z-=z_ofs;
#endif
vertex_interp = vertex.xyz;
normal_interp = normal;
@ -223,7 +208,41 @@ VERTEX_SHADER_CODE
binormal_interp = binormal;
#endif
#if !defined(SKIP_TRANSFORM_USED)
#ifdef RENDER_SHADOW
#ifdef RENDER_SHADOW_DUAL_PARABOLOID
vertex_interp.z*= shadow_dual_paraboloid_render_side;
normal_interp.z*= shadow_dual_paraboloid_render_side;
dp_clip=vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias
//for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges
highp vec3 vtx = vertex_interp+normalize(vertex_interp)*shadow_z_offset;
highp float distance = length(vtx);
vtx = normalize(vtx);
vtx.xy/=1.0-vtx.z;
vtx.z=(distance/shadow_dual_paraboloid_render_zfar);
vtx.z=vtx.z * 2.0 - 1.0;
vertex.xyz=vtx;
vertex.w=1.0;
#else
float z_ofs = shadow_z_offset;
z_ofs += (1.0-abs(normal_interp.z))*shadow_z_slope_scale;
vertex_interp.z-=z_ofs;
#endif //RENDER_SHADOW_DUAL_PARABOLOID
#endif //RENDER_SHADOW
#if !defined(SKIP_TRANSFORM_USED) && !defined(RENDER_SHADOW_DUAL_PARABOLOID)
gl_Position = projection_matrix * vec4(vertex_interp,1.0);
#else
gl_Position = vertex;
@ -239,11 +258,6 @@ VERTEX_SHADER_CODE
#define M_PI 3.14159265359
#define ENABLE_UV_INTERP
//hack to use uv if no uv present so it works with lightmap
/* Varyings */
#if defined(ENABLE_COLOR_INTERP)
@ -318,6 +332,15 @@ layout(std140) uniform SceneData {
highp vec4 bg_color;
float ambient_energy;
float bg_energy;
float shadow_z_offset;
float shadow_z_slope_scale;
float shadow_dual_paraboloid_render_zfar;
float shadow_dual_paraboloid_render_side;
vec2 shadow_atlas_pixel_size;
vec2 directional_shadow_pixel_size;
};
@ -328,7 +351,8 @@ layout(std140) uniform LightData {
highp vec4 light_pos_inv_radius;
mediump vec4 light_direction_attenuation;
mediump vec4 light_color_energy;
mediump vec4 light_params; //cone attenuation, specular, shadow darkening,
mediump vec4 light_params; //cone attenuation, specular, shadow darkening, shadow enabled
mediump vec4 light_clamp;
mediump vec4 shadow_split_offsets;
highp mat4 shadow_matrix1;
highp mat4 shadow_matrix2;
@ -336,20 +360,12 @@ layout(std140) uniform LightData {
highp mat4 shadow_matrix4;
};
#ifdef USE_FORWARD_1_SHADOW_MAP
in mediump vec4 forward_shadow_pos1;
#endif
#ifdef USE_FORWARD_2_SHADOW_MAP
in mediump vec4 forward_shadow_pos2;
#endif
#ifdef USE_FORWARD_4_SHADOW_MAP
in mediump vec4 forward_shadow_pos3;
in mediump vec4 forward_shadow_pos4;
#endif
uniform highp sampler2DShadow directional_shadow; //texunit:-4
uniform highp sampler2DShadow shadow_atlas; //texunit:-3
#endif
#ifdef USE_MULTIPLE_RENDER_TARGETS
@ -408,10 +424,27 @@ void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 diffuse_color,
}
float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 pos, float depth, vec4 clamp_rect) {
return textureProj(shadow,vec4(pos,depth,1.0));
}
#ifdef RENDER_SHADOW_DUAL_PARABOLOID
in highp float dp_clip;
#endif
void main() {
#ifdef RENDER_SHADOW_DUAL_PARABOLOID
if (dp_clip>0.0)
discard;
#endif
//lay out everything, whathever is unused is optimized away anyway
vec3 vertex = vertex_interp;
highp vec3 vertex = vertex_interp;
vec3 albedo = vec3(0.8,0.8,0.8);
vec3 specular = vec3(0.2,0.2,0.2);
float roughness = 1.0;
@ -528,27 +561,216 @@ FRAGMENT_SHADER_CODE
#endif
#ifdef USE_FORWARD_LIGHTING
#ifdef USE_FORWARD_DIRECTIONAL
light_compute(normal,light_direction_attenuation.xyz,eye_vec,albedo,specular,roughness,1.0,diffuse_light,specular_light);
float light_attenuation=1.0;
#ifdef LIGHT_DIRECTIONAL_SHADOW
if (gl_FragCoord.w > shadow_split_offsets.w) {
vec3 pssm_coord;
#ifdef LIGHT_USE_PSSM_BLEND
float pssm_blend;
vec3 pssm_coord2;
bool use_blend=true;
vec3 light_pssm_split_inv = 1.0/shadow_split_offsets.xyz;
float w_inv = 1.0/gl_FragCoord.w;
#endif
#ifdef LIGHT_USE_PSSM4
if (gl_FragCoord.w > shadow_split_offsets.y) {
if (gl_FragCoord.w > shadow_split_offsets.x) {
highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0));
pssm_coord=splane.xyz/splane.w;
ambient_light=vec3(1.0,0.4,0.4);
#if defined(LIGHT_USE_PSSM_BLEND)
splane=(shadow_matrix2 * vec4(vertex,1.0));
pssm_coord2=splane.xyz/splane.w;
pssm_blend=smoothstep(0.0,light_pssm_split_inv.x,w_inv);
#endif
} else {
highp vec4 splane=(shadow_matrix2 * vec4(vertex,1.0));
pssm_coord=splane.xyz/splane.w;
ambient_light=vec3(0.4,1.0,0.4);
#if defined(LIGHT_USE_PSSM_BLEND)
splane=(shadow_matrix3 * vec4(vertex,1.0));
pssm_coord2=splane.xyz/splane.w;
pssm_blend=smoothstep(light_pssm_split_inv.x,light_pssm_split_inv.y,w_inv);
#endif
}
} else {
if (gl_FragCoord.w > shadow_split_offsets.z) {
highp vec4 splane=(shadow_matrix3 * vec4(vertex,1.0));
pssm_coord=splane.xyz/splane.w;
ambient_light=vec3(0.4,0.4,1.0);
#if defined(LIGHT_USE_PSSM_BLEND)
splane=(shadow_matrix4 * vec4(vertex,1.0));
pssm_coord2=splane.xyz/splane.w;
pssm_blend=smoothstep(light_pssm_split_inv.y,light_pssm_split_inv.z,w_inv);
#endif
} else {
highp vec4 splane=(shadow_matrix4 * vec4(vertex,1.0));
pssm_coord=splane.xyz/splane.w;
diffuse_light*=vec3(1.0,0.4,1.0);
#if defined(LIGHT_USE_PSSM_BLEND)
use_blend=false;
#endif
}
}
#endif //LIGHT_USE_PSSM4
#ifdef LIGHT_USE_PSSM2
if (gl_FragCoord.w > shadow_split_offsets.x) {
highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0));
pssm_coord=splane.xyz/splane.w;
#if defined(LIGHT_USE_PSSM_BLEND)
splane=(shadow_matrix2 * vec4(vertex,1.0));
pssm_coord2=splane.xyz/splane.w;
pssm_blend=smoothstep(0.0,light_pssm_split_inv.x,w_inv);
#endif
} else {
highp vec4 splane=(shadow_matrix2 * vec4(vertex,1.0));
pssm_coord=splane.xyz/splane.w;
#if defined(LIGHT_USE_PSSM_BLEND)
use_blend=false;
#endif
}
#endif //LIGHT_USE_PSSM2
#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2)
{ //regular orthogonal
highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0));
pssm_coord=splane.xyz/splane.w;
}
#endif
//one one sample
light_attenuation=sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord.xy,pssm_coord.z,light_clamp);
#if defined(LIGHT_USE_PSSM_BLEND)
if (use_blend) {
float light_attenuation2=sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord2.xy,pssm_coord2.z,light_clamp);
light_attenuation=mix(light_attenuation,light_attenuation2,pssm_blend);
}
#endif
}
#endif //LIGHT_DIRECTIONAL_SHADOW
light_compute(normal,-light_direction_attenuation.xyz,eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light);
#endif //USE_FORWARD_DIRECTIONAL
#ifdef USE_FORWARD_OMNI
vec3 light_rel_vec = light_pos_inv_radius.xyz-vertex;
float normalized_distance = length( light_rel_vec )*light_pos_inv_radius.w;
float light_attenuation = pow( max(1.0 - normalized_distance, 0.0), light_direction_attenuation.w );
if (light_params.w>0.5) {
//there is a shadowmap
highp vec3 splane=(shadow_matrix1 * vec4(vertex,1.0)).xyz;
float shadow_len=length(splane);
splane=normalize(splane);
vec4 clamp_rect=light_clamp;
if (splane.z>=0.0) {
splane.z+=1.0;
clamp_rect.y+=clamp_rect.w;
} else {
splane.z=1.0 - splane.z;
//if (clamp_rect.z<clamp_rect.w) {
// clamp_rect.x+=clamp_rect.z;
//} else {
// clamp_rect.y+=clamp_rect.w;
//}
}
splane.xy/=splane.z;
splane.xy=splane.xy * 0.5 + 0.5;
splane.z = shadow_len * light_pos_inv_radius.w;
splane.xy = clamp_rect.xy+splane.xy*clamp_rect.zw;
light_attenuation*=sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,clamp_rect);
}
light_compute(normal,normalize(light_rel_vec),eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light);
#endif
#endif //USE_FORWARD_OMNI
#ifdef USE_FORWARD_SPOT
#endif
vec3 light_rel_vec = light_pos_inv_radius.xyz-vertex;
float normalized_distance = length( light_rel_vec )*light_pos_inv_radius.w;
float light_attenuation = pow( max(1.0 - normalized_distance, 0.0), light_direction_attenuation.w );
vec3 spot_dir = light_direction_attenuation.xyz;
float spot_cutoff=light_params.y;
float scos = max(dot(-normalize(light_rel_vec), spot_dir),spot_cutoff);
float rim = (1.0 - scos) / (1.0 - spot_cutoff);
light_attenuation *= 1.0 - pow( rim, light_params.x);
if (light_params.w>0.5) {
//there is a shadowmap
highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0));
splane.xyz/=splane.w;
// splane.xy=splane.xy*0.5+0.5;
//splane.xy=light_clamp.xy+splane.xy*light_clamp.zw;
light_attenuation*=sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,light_clamp);
}
light_compute(normal,normalize(light_rel_vec),eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light);
#endif //USE_FORWARD_SPOT
#endif
#if defined(USE_LIGHT_SHADER_CODE)
@ -560,6 +782,11 @@ LIGHT_SHADER_CODE
}
#endif
#ifdef RENDER_SHADOW
//nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
#else
#ifdef USE_MULTIPLE_RENDER_TARGETS
//approximate ambient scale for SSAO, since we will lack full ambient
@ -574,13 +801,17 @@ LIGHT_SHADER_CODE
#else
#ifdef SHADELESS
frag_color=vec4(albedo,alpha);
#else
frag_color=vec4(ambient_light+diffuse_light+specular_light,alpha);
#endif
#endif //SHADELESS
#endif //USE_MULTIPLE_RENDER_TARGETS
#endif //RENDER_SHADOW
#endif
}

View file

@ -1296,6 +1296,17 @@ bool Main::start() {
appname = TranslationServer::get_singleton()->translate(appname);
OS::get_singleton()->set_window_title(appname);
int shadow_atlas_size = GLOBAL_DEF("rendering/shadow_atlas/size",2048);
int shadow_atlas_q0_subdiv = GLOBAL_DEF("rendering/shadow_atlas/quadrant_0_subdiv",2);
int shadow_atlas_q1_subdiv = GLOBAL_DEF("rendering/shadow_atlas/quadrant_1_subdiv",2);
int shadow_atlas_q2_subdiv = GLOBAL_DEF("rendering/shadow_atlas/quadrant_2_subdiv",3);
int shadow_atlas_q3_subdiv = GLOBAL_DEF("rendering/shadow_atlas/quadrant_3_subdiv",4);
sml->get_root()->set_shadow_atlas_size(shadow_atlas_size);
sml->get_root()->set_shadow_atlas_quadrant_subdiv(0,Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q0_subdiv));
sml->get_root()->set_shadow_atlas_quadrant_subdiv(1,Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q1_subdiv));
sml->get_root()->set_shadow_atlas_quadrant_subdiv(2,Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q2_subdiv));
sml->get_root()->set_shadow_atlas_quadrant_subdiv(3,Viewport::ShadowAtlasQuadrantSubdiv(shadow_atlas_q3_subdiv));
} else {
GLOBAL_DEF("display/stretch_mode","disabled");
@ -1304,7 +1315,17 @@ bool Main::start() {
Globals::get_singleton()->set_custom_property_info("display/stretch_aspect",PropertyInfo(Variant::STRING,"display/stretch_aspect",PROPERTY_HINT_ENUM,"ignore,keep,keep_width,keep_height"));
sml->set_auto_accept_quit(GLOBAL_DEF("application/auto_accept_quit",true));
GLOBAL_DEF("rendering/shadow_atlas/size",2048);
Globals::get_singleton()->set_custom_property_info("rendering/shadow_atlas/size",PropertyInfo(Variant::INT,"rendering/shadow_atlas/size",PROPERTY_HINT_RANGE,"256,16384"));
GLOBAL_DEF("rendering/shadow_atlas/quadrant_0_subdiv",2);
GLOBAL_DEF("rendering/shadow_atlas/quadrant_1_subdiv",2);
GLOBAL_DEF("rendering/shadow_atlas/quadrant_2_subdiv",3);
GLOBAL_DEF("rendering/shadow_atlas/quadrant_3_subdiv",4);
Globals::get_singleton()->set_custom_property_info("rendering/shadow_atlas/quadrant_0_subdiv",PropertyInfo(Variant::INT,"rendering/shadow_atlas/quadrant_0_subdiv",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
Globals::get_singleton()->set_custom_property_info("rendering/shadow_atlas/quadrant_1_subdiv",PropertyInfo(Variant::INT,"rendering/shadow_atlas/quadrant_1_subdiv",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
Globals::get_singleton()->set_custom_property_info("rendering/shadow_atlas/quadrant_2_subdiv",PropertyInfo(Variant::INT,"rendering/shadow_atlas/quadrant_2_subdiv",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
Globals::get_singleton()->set_custom_property_info("rendering/shadow_atlas/quadrant_3_subdiv",PropertyInfo(Variant::INT,"rendering/shadow_atlas/quadrant_3_subdiv",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"));
}

View file

@ -202,7 +202,7 @@ void Light::_bind_methods() {
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "light/negative"), _SCS("set_negative"), _SCS("is_negative"));
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "light/specular"), _SCS("set_param"), _SCS("get_param"), PARAM_SPECULAR);
ADD_PROPERTY( PropertyInfo( Variant::INT, "light/cull_mask"), _SCS("set_cull_mask"), _SCS("get_cull_mask"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "shadow/enabled"), _SCS("set_shadow"), _SCS("has_shadow"));
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "shadow/enabled"), _SCS("set_shadow"), _SCS("has_shadow"));
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/darkness"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_DARKNESS);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/normal_bias"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_NORMAL_BIAS);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/bias"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_BIAS);
@ -222,7 +222,6 @@ void Light::_bind_methods() {
BIND_CONSTANT( PARAM_SHADOW_SPLIT_1_OFFSET );
BIND_CONSTANT( PARAM_SHADOW_SPLIT_2_OFFSET );
BIND_CONSTANT( PARAM_SHADOW_SPLIT_3_OFFSET );
BIND_CONSTANT( PARAM_SHADOW_SPLIT_4_OFFSET );
BIND_CONSTANT( PARAM_SHADOW_NORMAL_BIAS );
BIND_CONSTANT( PARAM_SHADOW_BIAS );
BIND_CONSTANT( PARAM_SHADOW_BIAS_SPLIT_SCALE );
@ -255,7 +254,6 @@ Light::Light(VisualServer::LightType p_type) {
set_param(PARAM_SHADOW_SPLIT_1_OFFSET,0.1);
set_param(PARAM_SHADOW_SPLIT_2_OFFSET,0.2);
set_param(PARAM_SHADOW_SPLIT_3_OFFSET,0.5);
set_param(PARAM_SHADOW_SPLIT_4_OFFSET,1.0);
set_param(PARAM_SHADOW_NORMAL_BIAS,0.1);
set_param(PARAM_SHADOW_BIAS,0.1);
set_param(PARAM_SHADOW_BIAS_SPLIT_SCALE,0.1);
@ -279,36 +277,107 @@ Light::~Light() {
}
/////////////////////////////////////////
void DirectionalLight::set_shadow_mode(ShadowMode p_mode) {
shadow_mode=p_mode;
VS::get_singleton()->light_directional_set_shadow_mode(light,VS::LightDirectionalShadowMode(p_mode));
}
DirectionalLight::ShadowMode DirectionalLight::get_shadow_mode() const {
return shadow_mode;
}
void DirectionalLight::set_blend_splits(bool p_enable) {
blend_splits=p_enable;
}
bool DirectionalLight::is_blend_splits_enabled() const {
return blend_splits;
}
void DirectionalLight::_bind_methods() {
ObjectTypeDB::bind_method( _MD("set_shadow_mode","mode"),&DirectionalLight::set_shadow_mode);
ObjectTypeDB::bind_method( _MD("get_shadow_mode"),&DirectionalLight::get_shadow_mode);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "pssm/split_1"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_1_OFFSET);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "pssm/split_2"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_2_OFFSET);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "pssm/split_3"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_3_OFFSET);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "pssm/split_4"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_4_OFFSET);
ObjectTypeDB::bind_method( _MD("set_blend_splits","enabled"),&DirectionalLight::set_blend_splits);
ObjectTypeDB::bind_method( _MD("is_blend_splits_enabled"),&DirectionalLight::is_blend_splits_enabled);
ADD_PROPERTY( PropertyInfo( Variant::INT, "directional/shadow_mode",PROPERTY_HINT_ENUM,"Orthogonal,PSSM 2 Splits,PSSM 4 Splits"), _SCS("set_shadow_mode"), _SCS("get_shadow_mode"));
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional/split_1"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_1_OFFSET);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional/split_2"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_2_OFFSET);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "directional/split_3"), _SCS("set_param"), _SCS("get_param"), PARAM_SHADOW_SPLIT_3_OFFSET);
ADD_PROPERTY( PropertyInfo( Variant::BOOL, "directional/blend_splits"), _SCS("set_blend_splits"), _SCS("is_blend_splits_enabled"));
BIND_CONSTANT( SHADOW_ORTHOGONAL );
BIND_CONSTANT( SHADOW_PARALLEL_2_SPLITS );
BIND_CONSTANT( SHADOW_PARALLEL_4_SPLITS );
}
DirectionalLight::DirectionalLight() : Light( VisualServer::LIGHT_DIRECTIONAL ) {
set_shadow_mode(SHADOW_PARALLEL_4_SPLITS);
blend_splits=false;
}
void OmniLight::set_shadow_mode(ShadowMode p_mode) {
shadow_mode=p_mode;
VS::get_singleton()->light_omni_set_shadow_mode(light,VS::LightOmniShadowMode(p_mode));
}
OmniLight::ShadowMode OmniLight::get_shadow_mode() const{
return shadow_mode;
}
void OmniLight::set_shadow_detail(ShadowDetail p_detail){
shadow_detail=p_detail;
VS::get_singleton()->light_omni_set_shadow_detail(light,VS::LightOmniShadowDetail(p_detail));
}
OmniLight::ShadowDetail OmniLight::get_shadow_detail() const{
return shadow_detail;
}
void OmniLight::_bind_methods() {
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "light/range"), _SCS("set_param"), _SCS("get_param"), PARAM_RANGE);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "light/attenuation"), _SCS("set_param"), _SCS("get_param"), PARAM_ATTENUATION);
ObjectTypeDB::bind_method( _MD("set_shadow_mode","mode"),&OmniLight::set_shadow_mode);
ObjectTypeDB::bind_method( _MD("get_shadow_mode"),&OmniLight::get_shadow_mode);
ObjectTypeDB::bind_method( _MD("set_shadow_detail","detail"),&OmniLight::set_shadow_detail);
ObjectTypeDB::bind_method( _MD("get_shadow_detail"),&OmniLight::get_shadow_detail);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "omni/range"), _SCS("set_param"), _SCS("get_param"), PARAM_RANGE);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "omni/attenuation"), _SCS("set_param"), _SCS("get_param"), PARAM_ATTENUATION);
ADD_PROPERTY( PropertyInfo( Variant::INT, "omni/shadow_mode",PROPERTY_HINT_ENUM,"Dual Paraboloid,Cube"), _SCS("set_shadow_mode"), _SCS("get_shadow_mode"));
ADD_PROPERTY( PropertyInfo( Variant::INT, "omni/shadow_detail",PROPERTY_HINT_ENUM,"Vertical,Horizontal"), _SCS("set_shadow_detail"), _SCS("get_shadow_detail"));
}
OmniLight::OmniLight() : Light( VisualServer::LIGHT_OMNI ) {
set_shadow_mode(SHADOW_DUAL_PARABOLOID);
set_shadow_detail(SHADOW_DETAIL_HORIZONTAL);
}
void SpotLight::_bind_methods() {
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "light/spot_angle"), _SCS("set_param"), _SCS("get_param"), PARAM_SPOT_ANGLE);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "light/spot_attenuation"), _SCS("set_param"), _SCS("get_param"), PARAM_SPOT_ATTENUATION);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot/range"), _SCS("set_param"), _SCS("get_param"), PARAM_RANGE);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot/attenuation"), _SCS("set_param"), _SCS("get_param"), PARAM_ATTENUATION);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot/spot_angle"), _SCS("set_param"), _SCS("get_param"), PARAM_SPOT_ANGLE);
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "spot/spot_attenuation"), _SCS("set_param"), _SCS("get_param"), PARAM_SPOT_ATTENUATION);
}

View file

@ -45,22 +45,21 @@ class Light : public VisualInstance {
public:
enum Param {
PARAM_ENERGY,
PARAM_SPECULAR,
PARAM_RANGE,
PARAM_ATTENUATION,
PARAM_SPOT_ANGLE,
PARAM_SPOT_ATTENUATION,
PARAM_SHADOW_MAX_DISTANCE,
PARAM_SHADOW_DARKNESS,
PARAM_SHADOW_SPLIT_1_OFFSET,
PARAM_SHADOW_SPLIT_2_OFFSET,
PARAM_SHADOW_SPLIT_3_OFFSET,
PARAM_SHADOW_SPLIT_4_OFFSET,
PARAM_SHADOW_NORMAL_BIAS,
PARAM_SHADOW_BIAS,
PARAM_SHADOW_BIAS_SPLIT_SCALE,
PARAM_MAX
PARAM_ENERGY = VS::LIGHT_PARAM_ENERGY,
PARAM_SPECULAR = VS::LIGHT_PARAM_SPECULAR,
PARAM_RANGE = VS::LIGHT_PARAM_RANGE,
PARAM_ATTENUATION = VS::LIGHT_PARAM_ATTENUATION,
PARAM_SPOT_ANGLE = VS::LIGHT_PARAM_SPOT_ANGLE,
PARAM_SPOT_ATTENUATION = VS::LIGHT_PARAM_SPOT_ATTENUATION,
PARAM_SHADOW_MAX_DISTANCE = VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE,
PARAM_SHADOW_DARKNESS = VS::LIGHT_PARAM_SHADOW_DARKNESS,
PARAM_SHADOW_SPLIT_1_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
PARAM_SHADOW_SPLIT_2_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
PARAM_SHADOW_SPLIT_3_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET,
PARAM_SHADOW_NORMAL_BIAS = VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS,
PARAM_SHADOW_BIAS = VS::LIGHT_PARAM_SHADOW_BIAS,
PARAM_SHADOW_BIAS_SPLIT_SCALE = VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,
PARAM_MAX = VS::LIGHT_PARAM_MAX
};
private:
@ -126,31 +125,69 @@ class DirectionalLight : public Light {
public:
enum ShadowMode {
SHADOW_ORTHOGONAL,
SHADOW_PARALLEL_2_SPLITS,
SHADOW_PARALLEL_4_SPLITS
};
private:
bool blend_splits;
ShadowMode shadow_mode;
protected:
static void _bind_methods();
public:
void set_shadow_mode(ShadowMode p_mode);
ShadowMode get_shadow_mode() const;
void set_blend_splits(bool p_enable);
bool is_blend_splits_enabled() const;
DirectionalLight();
};
VARIANT_ENUM_CAST(DirectionalLight::ShadowMode)
class OmniLight : public Light {
OBJ_TYPE( OmniLight, Light );
public:
// omni light
enum ShadowMode {
SHADOW_DUAL_PARABOLOID,
SHADOW_CUBE,
};
// omni light
enum ShadowDetail {
SHADOW_DETAIL_VERTICAL,
SHADOW_DETAIL_HORIZONTAL
};
private:
ShadowMode shadow_mode;
ShadowDetail shadow_detail;
protected:
static void _bind_methods();
public:
void set_shadow_mode(ShadowMode p_mode);
ShadowMode get_shadow_mode() const;
OmniLight() : Light( VisualServer::LIGHT_OMNI ) { }
void set_shadow_detail(ShadowDetail p_detail);
ShadowDetail get_shadow_detail() const;
OmniLight();
};
VARIANT_ENUM_CAST(OmniLight::ShadowMode)
VARIANT_ENUM_CAST(OmniLight::ShadowDetail)
class SpotLight : public Light {
OBJ_TYPE( SpotLight, Light );

View file

@ -201,7 +201,7 @@ Ref<Mesh> NavigationMesh::get_debug_mesh() {
arr.resize(Mesh::ARRAY_MAX);
arr[Mesh::ARRAY_VERTEX]=varr;
debug_mesh->add_surface(Mesh::PRIMITIVE_LINES,arr);
debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES,arr);
return debug_mesh;
}

View file

@ -845,7 +845,7 @@ Ref<Mesh> SceneTree::get_debug_contact_mesh() {
arr[Mesh::ARRAY_INDEX]=indices;
debug_contact_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,arr);
debug_contact_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES,arr);
debug_contact_mesh->surface_set_material(0,mat);
return debug_contact_mesh;

View file

@ -1297,6 +1297,39 @@ bool Viewport::get_clear_on_new_frame() const{
return clear_on_new_frame;
}
void Viewport::set_shadow_atlas_size(int p_size) {
shadow_atlas_size=p_size;
VS::get_singleton()->viewport_set_shadow_atlas_size(viewport,p_size);
}
int Viewport::get_shadow_atlas_size() const{
return shadow_atlas_size;
}
void Viewport::set_shadow_atlas_quadrant_subdiv(int p_quadrant,ShadowAtlasQuadrantSubdiv p_subdiv){
ERR_FAIL_INDEX(p_quadrant,4);
ERR_FAIL_INDEX(p_subdiv,SHADOW_ATLAS_QUADRANT_SUBDIV_MAX);
if (shadow_atlas_quadrant_subdiv[p_quadrant]==p_subdiv)
return;
shadow_atlas_quadrant_subdiv[p_quadrant]=p_subdiv;
static const int subdiv[SHADOW_ATLAS_QUADRANT_SUBDIV_MAX]={0,1,4,16,64,256,1024};
VS::get_singleton()->viewport_set_shadow_atlas_quadrant_subdivision(viewport,p_quadrant,subdiv[p_subdiv]);
}
Viewport::ShadowAtlasQuadrantSubdiv Viewport::get_shadow_atlas_quadrant_subdiv(int p_quadrant) const{
ERR_FAIL_INDEX_V(p_quadrant,4,SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED);
return shadow_atlas_quadrant_subdiv[p_quadrant];
}
void Viewport::clear() {
//clear=true;
@ -2661,6 +2694,12 @@ void Viewport::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_gui_show_tooltip"), &Viewport::_gui_show_tooltip);
ObjectTypeDB::bind_method(_MD("_gui_remove_focus"), &Viewport::_gui_remove_focus);
ObjectTypeDB::bind_method(_MD("set_shadow_atlas_size","size"), &Viewport::set_shadow_atlas_size);
ObjectTypeDB::bind_method(_MD("get_shadow_atlas_size"), &Viewport::get_shadow_atlas_size);
ObjectTypeDB::bind_method(_MD("set_shadow_atlas_quadrant_subdiv","quadrant","subdiv"), &Viewport::set_shadow_atlas_quadrant_subdiv);
ObjectTypeDB::bind_method(_MD("get_shadow_atlas_quadrant_subdiv","quadrant"), &Viewport::get_shadow_atlas_quadrant_subdiv);
ADD_PROPERTY( PropertyInfo(Variant::RECT2,"size"), _SCS("set_size"), _SCS("get_size") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"own_world"), _SCS("set_use_own_world"), _SCS("is_using_own_world") );
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"world",PROPERTY_HINT_RESOURCE_TYPE,"World"), _SCS("set_world"), _SCS("get_world") );
@ -2674,6 +2713,11 @@ void Viewport::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"physics/object_picking"), _SCS("set_physics_object_picking"), _SCS("get_physics_object_picking") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"gui/disable_input"), _SCS("set_disable_input"), _SCS("is_input_disabled") );
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"3d/disable_3d"), _SCS("set_disable_3d"), _SCS("is_3d_disabled") );
ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow_atlas/size"), _SCS("set_shadow_atlas_size"), _SCS("get_shadow_atlas_size") );
ADD_PROPERTYI( PropertyInfo(Variant::INT,"shadow_atlas/quad_0",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), _SCS("set_shadow_atlas_quadrant_subdiv"), _SCS("get_shadow_atlas_quadrant_subdiv"),0 );
ADD_PROPERTYI( PropertyInfo(Variant::INT,"shadow_atlas/quad_1",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), _SCS("set_shadow_atlas_quadrant_subdiv"), _SCS("get_shadow_atlas_quadrant_subdiv"),1 );
ADD_PROPERTYI( PropertyInfo(Variant::INT,"shadow_atlas/quad_2",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), _SCS("set_shadow_atlas_quadrant_subdiv"), _SCS("get_shadow_atlas_quadrant_subdiv"),2 );
ADD_PROPERTYI( PropertyInfo(Variant::INT,"shadow_atlas/quad_3",PROPERTY_HINT_ENUM,"Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), _SCS("set_shadow_atlas_quadrant_subdiv"), _SCS("get_shadow_atlas_quadrant_subdiv"),3 );
ADD_SIGNAL(MethodInfo("size_changed"));
@ -2682,6 +2726,14 @@ void Viewport::_bind_methods() {
BIND_CONSTANT( UPDATE_WHEN_VISIBLE );
BIND_CONSTANT( UPDATE_ALWAYS );
BIND_CONSTANT( SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED );
BIND_CONSTANT( SHADOW_ATLAS_QUADRANT_SUBDIV_1 );
BIND_CONSTANT( SHADOW_ATLAS_QUADRANT_SUBDIV_4 );
BIND_CONSTANT( SHADOW_ATLAS_QUADRANT_SUBDIV_16 );
BIND_CONSTANT( SHADOW_ATLAS_QUADRANT_SUBDIV_64 );
BIND_CONSTANT( SHADOW_ATLAS_QUADRANT_SUBDIV_256 );
BIND_CONSTANT( SHADOW_ATLAS_QUADRANT_SUBDIV_1024 );
BIND_CONSTANT( SHADOW_ATLAS_QUADRANT_SUBDIV_MAX );
}
@ -2719,6 +2771,15 @@ Viewport::Viewport() {
physics_object_over=0;
physics_last_mousepos=Vector2(1e20,1e20);
shadow_atlas_size=0;
for(int i=0;i<4;i++) {
shadow_atlas_quadrant_subdiv[0]=SHADOW_ATLAS_QUADRANT_SUBDIV_MAX;
}
set_shadow_atlas_quadrant_subdiv(0,SHADOW_ATLAS_QUADRANT_SUBDIV_4);
set_shadow_atlas_quadrant_subdiv(1,SHADOW_ATLAS_QUADRANT_SUBDIV_4);
set_shadow_atlas_quadrant_subdiv(2,SHADOW_ATLAS_QUADRANT_SUBDIV_16);
set_shadow_atlas_quadrant_subdiv(3,SHADOW_ATLAS_QUADRANT_SUBDIV_64);
String id=itos(get_instance_ID());
input_group = "_vp_input"+id;

View file

@ -86,6 +86,18 @@ public:
UPDATE_ALWAYS
};
enum ShadowAtlasQuadrantSubdiv {
SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED,
SHADOW_ATLAS_QUADRANT_SUBDIV_1,
SHADOW_ATLAS_QUADRANT_SUBDIV_4,
SHADOW_ATLAS_QUADRANT_SUBDIV_16,
SHADOW_ATLAS_QUADRANT_SUBDIV_64,
SHADOW_ATLAS_QUADRANT_SUBDIV_256,
SHADOW_ATLAS_QUADRANT_SUBDIV_1024,
SHADOW_ATLAS_QUADRANT_SUBDIV_MAX,
};
private:
friend class ViewportTexture;
@ -120,8 +132,6 @@ friend class ViewportTexture;
RID contact_3d_debug_multimesh;
RID contact_3d_debug_instance;
bool size_override;
bool size_override_stretch;
Size2 size_override_size;
@ -175,6 +185,9 @@ friend class ViewportTexture;
RID texture_rid;
Ref<ViewportTexture> texture;
int shadow_atlas_size;
ShadowAtlasQuadrantSubdiv shadow_atlas_quadrant_subdiv[4];
struct GUI {
// info used when this is a window
@ -347,6 +360,11 @@ public:
UpdateMode get_update_mode() const;
Ref<ViewportTexture> get_texture() const;
void set_shadow_atlas_size(int p_size);
int get_shadow_atlas_size() const;
void set_shadow_atlas_quadrant_subdiv(int p_quadrant,ShadowAtlasQuadrantSubdiv p_subdiv);
ShadowAtlasQuadrantSubdiv get_shadow_atlas_quadrant_subdiv(int p_quadrant) const;
Vector2 get_camera_coords(const Vector2& p_viewport_coords) const;
Vector2 get_camera_rect_size() const;
@ -393,4 +411,6 @@ public:
};
VARIANT_ENUM_CAST(Viewport::UpdateMode);
VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv);
#endif

View file

@ -152,7 +152,7 @@ void FixedSpatialMaterial::_update_shader() {
switch(cull_mode) {
case CULL_BACK: code+=",cull_back"; break;
case CULL_FRONT: code+=",cull_front"; break;
case CULL_DISABLED: code+=",cull_disable"; break;
case CULL_DISABLED: code+=",cull_disabled"; break;
}

View file

@ -125,11 +125,61 @@ bool Mesh::_set(const StringName& p_name, const Variant& p_value) {
//create
Dictionary d=p_value;
ERR_FAIL_COND_V(!d.has("primitive"),false);
ERR_FAIL_COND_V(!d.has("arrays"),false);
ERR_FAIL_COND_V(!d.has("morph_arrays"),false);
if (d.has("arrays")) {
//old format
ERR_FAIL_COND_V(!d.has("morph_arrays"),false);
add_surface_from_arrays(PrimitiveType(int(d["primitive"])),d["arrays"],d["morph_arrays"]);
} else if (d.has("array_data")) {
DVector<uint8_t> array_data = d["array_data"];
DVector<uint8_t> array_index_data;
if (d.has("array_index_data"))
array_index_data=d["array_index_data"];
ERR_FAIL_COND_V(!d.has("format"),false);
uint32_t format = d["format"];
ERR_FAIL_COND_V(!d.has("primitive"),false);
uint32_t primitive = d["primitive"];
ERR_FAIL_COND_V(!d.has("vertex_count"),false);
int vertex_count = d["vertex_count"];
int index_count=0;
if (d.has("index_count"))
index_count=d["index_count"];
Vector< DVector<uint8_t> > morphs;
if (d.has("morph_data")) {
Array morph_data=d["morph_data"];
for(int i=0;i<morph_data.size();i++) {
DVector<uint8_t> morph = morph_data[i];
morphs.push_back(morph_data[i]);
}
}
ERR_FAIL_COND_V(!d.has("aabb"),false);
AABB aabb = d["aabb"];
Vector<AABB> bone_aabb;
if (d.has("bone_aabb")) {
Array baabb = d["bone_aabb"];
bone_aabb.resize(baabb.size());
for(int i=0;i<baabb.size();i++) {
bone_aabb[i]=baabb[i];
}
}
add_surface(format,PrimitiveType(primitive),array_data,vertex_count,array_index_data,index_count,aabb,morphs,bone_aabb);
} else {
ERR_FAIL_V(false);
}
add_surface(PrimitiveType(int(d["primitive"])),d["arrays"],d["morph_arrays"]);
if (d.has("material")) {
surface_set_material(idx,d["material"]);
@ -185,9 +235,31 @@ bool Mesh::_get(const StringName& p_name,Variant &r_ret) const {
ERR_FAIL_INDEX_V(idx,surfaces.size(),false);
Dictionary d;
d["primitive"]=surface_get_primitive_type(idx);
d["arrays"]=surface_get_arrays(idx);
d["morph_arrays"]=surface_get_morph_arrays(idx);
d["array_data"]=VS::get_singleton()->mesh_surface_get_array(mesh,idx);
d["vertex_count"]=VS::get_singleton()->mesh_surface_get_array_len(mesh,idx);
d["array_index_data"]=VS::get_singleton()->mesh_surface_get_index_array(mesh,idx);
d["index_count"]=VS::get_singleton()->mesh_surface_get_array_index_len(mesh,idx);
d["primitive"]=VS::get_singleton()->mesh_surface_get_primitive_type(mesh,idx);
d["format"]=VS::get_singleton()->mesh_surface_get_format(mesh,idx);
d["aabb"]=VS::get_singleton()->mesh_surface_get_aabb(mesh,idx);
Vector<AABB> skel_aabb = VS::get_singleton()->mesh_surface_get_skeleton_aabb(mesh,idx);
Array arr;
for(int i=0;i<skel_aabb.size();i++) {
arr[i]=skel_aabb[i];
}
d["skeleton_aabb"]=arr;
Vector< DVector<uint8_t> > morph_data = VS::get_singleton()->mesh_surface_get_blend_shapes(mesh,idx);
Array md;
for(int i=0;i<morph_data.size();i++) {
md.push_back(morph_data[i]);
}
d["morph_data"]=md;
Ref<Material> m = surface_get_material(idx);
if (m.is_valid())
d["material"]=m;
@ -234,7 +306,17 @@ void Mesh::_recompute_aabb() {
}
void Mesh::add_surface(PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes) {
void Mesh::add_surface(uint32_t p_format,PrimitiveType p_primitive,const DVector<uint8_t>& p_array,int p_vertex_count,const DVector<uint8_t>& p_index_array,int p_index_count,const AABB& p_aabb,const Vector<DVector<uint8_t> >& p_blend_shapes,const Vector<AABB>& p_bone_aabbs) {
Surface s;
s.aabb=p_aabb;
surfaces.push_back(s);
VisualServer::get_singleton()->mesh_add_surface(mesh,p_format,(VS::PrimitiveType)p_primitive,p_array,p_vertex_count,p_index_array,p_index_count,p_aabb,p_blend_shapes,p_bone_aabbs);
}
void Mesh::add_surface_from_arrays(PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes) {
ERR_FAIL_COND(p_arrays.size()!=ARRAY_MAX);
@ -279,8 +361,7 @@ void Mesh::add_surface(PrimitiveType p_primitive,const Array& p_arrays,const Arr
Array Mesh::surface_get_arrays(int p_surface) const {
ERR_FAIL_INDEX_V(p_surface,surfaces.size(),Array());
//return VisualServer::get_singleton()->mesh_get_surface_arrays(mesh,p_surface);
return Array();
return VisualServer::get_singleton()->mesh_surface_get_arrays(mesh,p_surface);
}
Array Mesh::surface_get_morph_arrays(int p_surface) const {
@ -929,7 +1010,7 @@ Ref<Mesh> Mesh::create_outline(float p_margin) const {
Ref<Mesh> newmesh = memnew( Mesh );
newmesh->add_surface(PRIMITIVE_TRIANGLES,arrays);
newmesh->add_surface_from_arrays(PRIMITIVE_TRIANGLES,arrays);
return newmesh;
}
@ -943,6 +1024,7 @@ void Mesh::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_morph_target_mode","mode"),&Mesh::set_morph_target_mode);
ObjectTypeDB::bind_method(_MD("get_morph_target_mode"),&Mesh::get_morph_target_mode);
ObjectTypeDB::bind_method(_MD("add_surface_from_arrays","primitive","arrays","blend_shapes"),&Mesh::add_surface_from_arrays,DEFVAL(Array()));
ObjectTypeDB::bind_method(_MD("get_surface_count"),&Mesh::get_surface_count);
ObjectTypeDB::bind_method(_MD("surface_remove","surf_idx"),&Mesh::surface_remove);
ObjectTypeDB::bind_method(_MD("surface_get_array_len","surf_idx"),&Mesh::surface_get_array_len);

View file

@ -122,7 +122,9 @@ protected:
public:
void add_surface(PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array());
void add_surface_from_arrays(PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array());
void add_surface(uint32_t p_format,PrimitiveType p_primitive,const DVector<uint8_t>& p_array,int p_vertex_count,const DVector<uint8_t>& p_index_array,int p_index_count,const AABB& p_aabb,const Vector<DVector<uint8_t> >& p_blend_shapes=Vector<DVector<uint8_t> >(),const Vector<AABB>& p_bone_aabbs=Vector<AABB>());
Array surface_get_arrays(int p_surface) const;
virtual Array surface_get_morph_arrays(int p_surface) const;

View file

@ -328,7 +328,7 @@ Error MeshDataTool::commit_to_surface(const Ref<Mesh>& p_mesh) {
Ref<Mesh> ncmesh=p_mesh;
int sc = ncmesh->get_surface_count();
ncmesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,arr);
ncmesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES,arr);
ncmesh->surface_set_material(sc,material);
return OK;

View file

@ -77,7 +77,7 @@ Ref<Mesh> Shape::get_debug_mesh() {
SceneTree *st=OS::get_singleton()->get_main_loop()->cast_to<SceneTree>();
debug_mesh_cache->add_surface(Mesh::PRIMITIVE_LINES,arr);
debug_mesh_cache->add_surface_from_arrays(Mesh::PRIMITIVE_LINES,arr);
if (st) {
debug_mesh_cache->surface_set_material(0,st->get_debug_collision_material());

View file

@ -410,7 +410,7 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh>& p_existing) {
}
mesh->add_surface(primitive,a);
mesh->add_surface_from_arrays(primitive,a);
if (material.is_valid())
mesh->surface_set_material(surface,material);

View file

@ -39,6 +39,16 @@
class RasterizerScene {
public:
/* SHADOW ATLAS API */
virtual RID shadow_atlas_create()=0;
virtual void shadow_atlas_set_size(RID p_atlas,int p_size)=0;
virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas,int p_quadrant,int p_subdivision)=0;
virtual bool shadow_atlas_update_light(RID p_atlas,RID p_light_intance,float p_coverage,uint64_t p_light_version)=0;
virtual int get_directional_light_shadow_size(RID p_light_intance)=0;
virtual void set_directional_shadow_count(int p_count)=0;
/* ENVIRONMENT API */
virtual RID environment_create()=0;
@ -93,6 +103,7 @@ public:
virtual void base_removed()=0;
virtual void base_changed()=0;
virtual void base_material_changed()=0;
InstanceBase() : dependency_item(this) {
@ -109,10 +120,11 @@ public:
virtual RID light_instance_create(RID p_light)=0;
virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform)=0;
virtual void light_instance_set_shadow_transform(RID p_light_instance,const CameraMatrix& p_projection,const Transform& p_transform,float p_far,float p_split,int p_pass)=0;
virtual void light_instance_mark_visible(RID p_light_instance)=0;
virtual void render_scene(const Transform& p_cam_transform,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_directional_lights,int p_directional_light_count,RID p_environment)=0;
virtual void render_scene(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_environment,RID p_shadow_atlas)=0;
virtual void render_shadow(RID p_light,RID p_shadow_atlas,int p_pass,InstanceBase** p_cull_result,int p_cull_count)=0;
virtual void set_scene_pass(uint64_t p_pass)=0;
@ -179,6 +191,12 @@ public:
virtual void material_set_line_width(RID p_material, float p_width)=0;
virtual bool material_is_animated(RID p_material)=0;
virtual bool material_casts_shadows(RID p_material)=0;
virtual void material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance)=0;
virtual void material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance)=0;
/* MESH API */
virtual RID mesh_create()=0;
@ -205,6 +223,10 @@ public:
virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const=0;
virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const=0;
virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const=0;
virtual Vector<DVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const=0;
virtual Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const=0;
virtual void mesh_remove_surface(RID p_mesh,int p_index)=0;
virtual int mesh_get_surface_count(RID p_mesh) const=0;
@ -279,10 +301,21 @@ public:
virtual void light_set_cull_mask(RID p_light,uint32_t p_mask)=0;
virtual void light_set_shader(RID p_light,RID p_shader)=0;
virtual void light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode)=0;
virtual void light_omni_set_shadow_detail(RID p_light,VS::LightOmniShadowDetail p_detail)=0;
virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode)=0;
virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light)=0;
virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light)=0;
virtual bool light_has_shadow(RID p_light) const=0;
virtual VS::LightType light_get_type(RID p_light) const=0;
virtual AABB light_get_aabb(RID p_light) const=0;
virtual float light_get_param(RID p_light,VS::LightParam p_param)=0;
virtual uint64_t light_get_version(RID p_light) const=0;
/* PROBE API */

View file

@ -84,7 +84,7 @@ ShaderTypes::ShaderTypes()
shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_front");
shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_back");
shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_disable");
shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_disabled");
shader_modes[VS::SHADER_SPATIAL].modes.insert("unshaded");
shader_modes[VS::SHADER_SPATIAL].modes.insert("ontop");

View file

@ -687,6 +687,10 @@ public:
BIND2RC(uint32_t,mesh_surface_get_format,RID,int)
BIND2RC(PrimitiveType,mesh_surface_get_primitive_type,RID,int)
BIND2RC(AABB,mesh_surface_get_aabb,RID,int)
BIND2RC(Vector<DVector<uint8_t> >,mesh_surface_get_blend_shapes,RID,int)
BIND2RC(Vector<AABB>,mesh_surface_get_skeleton_aabb,RID,int)
BIND2(mesh_remove_surface,RID,int)
BIND1RC(int,mesh_get_surface_count,RID)
@ -759,6 +763,9 @@ public:
BIND2(light_set_cull_mask,RID ,uint32_t )
BIND2(light_set_shader,RID ,RID )
BIND2(light_omni_set_shadow_mode,RID,LightOmniShadowMode)
BIND2(light_omni_set_shadow_detail,RID,LightOmniShadowDetail)
BIND2(light_directional_set_shadow_mode,RID,LightDirectionalShadowMode)
/* PROBE API */
@ -847,7 +854,8 @@ public:
BIND2(viewport_set_global_canvas_transform,RID,const Matrix32& )
BIND3(viewport_set_canvas_layer,RID ,RID ,int )
BIND2(viewport_set_shadow_atlas_size,RID ,int )
BIND3(viewport_set_shadow_atlas_quadrant_subdivision,RID ,int, int )
/* ENVIRONMENT API */

View file

@ -96,7 +96,10 @@ void* VisualServerScene::_instance_pair(void *p_self, OctreeElementID, Instance
List<InstanceLightData::PairInfo>::Element *E = light->geometries.push_back(pinfo);
light->shadow_sirty=true;
if (geom->can_cast_shadows) {
light->shadow_dirty=true;
}
geom->lighting_dirty=true;
return E; //this element should make freeing faster
@ -180,7 +183,9 @@ void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance
geom->lighting.erase(E->get().L);
light->geometries.erase(E);
light->shadow_sirty=true;
if (geom->can_cast_shadows) {
light->shadow_dirty=true;
}
geom->lighting_dirty=true;
@ -346,6 +351,12 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base){
}
instance->morph_values.clear();
for(int i=0;i<instance->materials.size();i++) {
if (instance->materials[i].is_valid()) {
VSG::storage->material_remove_instance_owner(instance->materials[i],instance);
}
}
instance->materials.clear();
#if 0
@ -667,7 +678,16 @@ void VisualServerScene::instance_set_surface_material(RID p_instance,int p_surfa
ERR_FAIL_INDEX(p_surface,instance->materials.size());
if (instance->materials[p_surface].is_valid()) {
VSG::storage->material_remove_instance_owner(instance->materials[p_surface],instance);
}
instance->materials[p_surface]=p_material;
instance->base_material_changed();
if (instance->materials[p_surface].is_valid()) {
VSG::storage->material_add_instance_owner(instance->materials[p_surface],instance);
}
}
@ -791,12 +811,14 @@ void VisualServerScene::instance_geometry_set_flag(RID p_instance,VS::InstanceFl
} break;
case VS::INSTANCE_FLAG_CAST_SHADOW: {
/*if (p_enabled == true) {
instance->cast_shadows = SHADOW_CASTING_SETTING_ON;
if (p_enabled == true) {
instance->cast_shadows = VS::SHADOW_CASTING_SETTING_ON;
}
else {
instance->cast_shadows = SHADOW_CASTING_SETTING_OFF;
}*/
instance->cast_shadows = VS::SHADOW_CASTING_SETTING_OFF;
}
instance->base_material_changed(); // to actually compute if shadows are visible or not
} break;
case VS::INSTANCE_FLAG_DEPH_SCALE: {
@ -820,8 +842,15 @@ void VisualServerScene::instance_geometry_set_material_override(RID p_instance,
Instance *instance = instance_owner.get( p_instance );
ERR_FAIL_COND( !instance );
if (instance->material_override.is_valid()) {
VSG::storage->material_remove_instance_owner(instance->material_override,instance);
}
instance->material_override=p_material;
instance->base_material_changed();
if (instance->material_override.is_valid()) {
VSG::storage->material_add_instance_owner(instance->material_override,instance);
}
}
@ -843,6 +872,7 @@ void VisualServerScene::_update_instance(Instance *p_instance) {
InstanceLightData *light = static_cast<InstanceLightData*>(p_instance->base_data);
VSG::scene_render->light_instance_set_transform( light->instance, p_instance->transform );
light->shadow_dirty=true;
}
@ -860,11 +890,13 @@ void VisualServerScene::_update_instance(Instance *p_instance) {
if ((1<<p_instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData*>(p_instance->base_data);
//make sure lights are updated
//make sure lights are updated if it casts shadow
for (List<Instance*>::Element *E=geom->lighting.front();E;E=E->next()) {
InstanceLightData *light = static_cast<InstanceLightData*>(E->get()->base_data);
light->shadow_sirty=true;
if (geom->can_cast_shadows) {
for (List<Instance*>::Element *E=geom->lighting.front();E;E=E->next()) {
InstanceLightData *light = static_cast<InstanceLightData*>(E->get()->base_data);
light->shadow_dirty=true;
}
}
}
@ -1095,9 +1127,371 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) {
void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewport_size) {
void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,Camera* p_camera,RID p_shadow_atlas,Scenario* p_scenario,Size2 p_viewport_rect) {
InstanceLightData * light = static_cast<InstanceLightData*>(p_instance->base_data);
switch(VSG::storage->light_get_type(p_instance->base)) {
case VS::LIGHT_DIRECTIONAL: {
float max_distance = p_camera->zfar;
float shadow_max = VSG::storage->light_get_param(p_instance->base,VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
if (shadow_max>0) {
max_distance=MIN(shadow_max,max_distance);
}
max_distance=MAX(max_distance,p_camera->znear+0.001);
float range = max_distance-p_camera->znear;
int splits=0;
switch(VSG::storage->light_directional_get_shadow_mode(p_instance->base)) {
case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: splits=1; break;
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: splits=2; break;
case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: splits=4; break;
}
float distances[5];
distances[0]=p_camera->znear;
for(int i=0;i<splits;i++) {
distances[i+1]=p_camera->znear+VSG::storage->light_get_param(p_instance->base,VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET+i))*range;
};
distances[splits]=max_distance;
float texture_size=VSG::scene_render->get_directional_light_shadow_size(light->instance);
bool overlap = false;//rasterizer->light_instance_get_pssm_shadow_overlap(p_light->light_info->instance);
for (int i=0;i<splits;i++) {
// setup a camera matrix for that range!
CameraMatrix camera_matrix;
switch(p_camera->type) {
case Camera::ORTHOGONAL: {
camera_matrix.set_orthogonal(
p_camera->size,
p_viewport_rect.width / p_viewport_rect.height,
distances[(i==0 || !overlap )?i:i-1],
distances[i+1],
p_camera->vaspect
);
} break;
case Camera::PERSPECTIVE: {
camera_matrix.set_perspective(
p_camera->fov,
p_viewport_rect.width / (float)p_viewport_rect.height,
distances[(i==0 || !overlap )?i:i-1],
distances[i+1],
p_camera->vaspect
);
} break;
}
//obtain the frustum endpoints
Vector3 endpoints[8]; // frustum plane endpoints
bool res = camera_matrix.get_endpoints(p_camera->transform,endpoints);
ERR_CONTINUE(!res);
// obtain the light frustm ranges (given endpoints)
Vector3 x_vec=p_instance->transform.basis.get_axis( Vector3::AXIS_X ).normalized();
Vector3 y_vec=p_instance->transform.basis.get_axis( Vector3::AXIS_Y ).normalized();
Vector3 z_vec=p_instance->transform.basis.get_axis( Vector3::AXIS_Z ).normalized();
//z_vec points agsint the camera, like in default opengl
float x_min,x_max;
float y_min,y_max;
float z_min,z_max;
float x_min_cam,x_max_cam;
float y_min_cam,y_max_cam;
float z_min_cam,z_max_cam;
//used for culling
for(int j=0;j<8;j++) {
float d_x=x_vec.dot(endpoints[j]);
float d_y=y_vec.dot(endpoints[j]);
float d_z=z_vec.dot(endpoints[j]);
if (j==0 || d_x<x_min)
x_min=d_x;
if (j==0 || d_x>x_max)
x_max=d_x;
if (j==0 || d_y<y_min)
y_min=d_y;
if (j==0 || d_y>y_max)
y_max=d_y;
if (j==0 || d_z<z_min)
z_min=d_z;
if (j==0 || d_z>z_max)
z_max=d_z;
}
{
//camera viewport stuff
//this trick here is what stabilizes the shadow (make potential jaggies to not move)
//at the cost of some wasted resolution. Still the quality increase is very well worth it
Vector3 center;
for(int j=0;j<8;j++) {
center+=endpoints[j];
}
center/=8.0;
//center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5;
float radius=0;
for(int j=0;j<8;j++) {
float d = center.distance_to(endpoints[j]);
if (d>radius)
radius=d;
}
radius *= texture_size/(texture_size-2.0); //add a texel by each side, so stepified texture will always fit
x_max_cam=x_vec.dot(center)+radius;
x_min_cam=x_vec.dot(center)-radius;
y_max_cam=y_vec.dot(center)+radius;
y_min_cam=y_vec.dot(center)-radius;
z_max_cam=z_vec.dot(center)+radius;
z_min_cam=z_vec.dot(center)-radius;
float unit = radius*2.0/texture_size;
x_max_cam=Math::stepify(x_max_cam,unit);
x_min_cam=Math::stepify(x_min_cam,unit);
y_max_cam=Math::stepify(y_max_cam,unit);
y_min_cam=Math::stepify(y_min_cam,unit);
}
//now that we now all ranges, we can proceed to make the light frustum planes, for culling octree
Vector<Plane> light_frustum_planes;
light_frustum_planes.resize(6);
//right/left
light_frustum_planes[0]=Plane( x_vec, x_max );
light_frustum_planes[1]=Plane( -x_vec, -x_min );
//top/bottom
light_frustum_planes[2]=Plane( y_vec, y_max );
light_frustum_planes[3]=Plane( -y_vec, -y_min );
//near/far
light_frustum_planes[4]=Plane( z_vec, z_max+1e6 );
light_frustum_planes[5]=Plane( -z_vec, -z_min ); // z_min is ok, since casters further than far-light plane are not needed
int cull_count = p_scenario->octree.cull_convex(light_frustum_planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK);
// a pre pass will need to be needed to determine the actual z-near to be used
for (int j=0;j<cull_count;j++) {
float min,max;
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) {
cull_count--;
SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]);
j--;
}
instance->transformed_aabb.project_range_in_plane(Plane(z_vec,0),min,max);
if (max>z_max)
z_max=max;
}
{
CameraMatrix ortho_camera;
real_t half_x = (x_max_cam-x_min_cam) * 0.5;
real_t half_y = (y_max_cam-y_min_cam) * 0.5;
ortho_camera.set_orthogonal( -half_x, half_x,-half_y,half_y, 0, (z_max-z_min_cam) );
Transform ortho_transform;
ortho_transform.basis=p_instance->transform.basis;
ortho_transform.origin=x_vec*(x_min_cam+half_x)+y_vec*(y_min_cam+half_y)+z_vec*z_max;
VSG::scene_render->light_instance_set_shadow_transform(light->instance,ortho_camera,ortho_transform,0,distances[i+1],i);
}
VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,i,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count);
}
} break;
case VS::LIGHT_OMNI: {
VS::LightOmniShadowMode shadow_mode = VSG::storage->light_omni_get_shadow_mode(p_instance->base);
switch(shadow_mode) {
case VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID: {
for(int i=0;i<2;i++) {
//using this one ensures that raster deferred will have it
float radius = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_RANGE);
float z =i==0?-1:1;
Vector<Plane> planes;
planes.resize(5);
planes[0]=p_instance->transform.xform(Plane(Vector3(0,0,z),radius));
planes[1]=p_instance->transform.xform(Plane(Vector3(1,0,z).normalized(),radius));
planes[2]=p_instance->transform.xform(Plane(Vector3(-1,0,z).normalized(),radius));
planes[3]=p_instance->transform.xform(Plane(Vector3(0,1,z).normalized(),radius));
planes[4]=p_instance->transform.xform(Plane(Vector3(0,-1,z).normalized(),radius));
int cull_count = p_scenario->octree.cull_convex(planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK);
for (int j=0;j<cull_count;j++) {
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) {
cull_count--;
SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]);
j--;
}
}
VSG::scene_render->light_instance_set_shadow_transform(light->instance,CameraMatrix(),p_instance->transform,radius,0,i);
VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,i,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count);
}
} break;
case VS::LIGHT_OMNI_SHADOW_CUBE: {
float radius = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_RANGE);
CameraMatrix cm;
cm.set_perspective(90,1,0.01,radius);
for(int i=0;i<6;i++) {
//using this one ensures that raster deferred will have it
static const Vector3 view_normals[6]={
Vector3(-1, 0, 0),
Vector3(+1, 0, 0),
Vector3( 0,-1, 0),
Vector3( 0,+1, 0),
Vector3( 0, 0,-1),
Vector3( 0, 0,+1)
};
static const Vector3 view_up[6]={
Vector3( 0,-1, 0),
Vector3( 0,-1, 0),
Vector3( 0, 0,-1),
Vector3( 0, 0,+1),
Vector3( 0,-1, 0),
Vector3( 0,-1, 0)
};
Transform xform = p_instance->transform * Transform().looking_at(view_normals[i],view_up[i]);
Vector<Plane> planes = cm.get_projection_planes(xform);
int cull_count = p_scenario->octree.cull_convex(planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK);
for (int j=0;j<cull_count;j++) {
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) {
cull_count--;
SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]);
j--;
}
}
VSG::scene_render->light_instance_set_shadow_transform(light->instance,cm,xform,radius,0,i);
VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,i,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count);
}
//restore the regular DP matrix
VSG::scene_render->light_instance_set_shadow_transform(light->instance,CameraMatrix(),p_instance->transform,radius,0,0);
} break;
}
} break;
case VS::LIGHT_SPOT: {
float radius = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_RANGE);
float angle = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_SPOT_ANGLE);
CameraMatrix cm;
cm.set_perspective( 90, 1.0, 0.01, radius );
print_line("perspective: "+cm);
Vector<Plane> planes = cm.get_projection_planes(p_instance->transform);
int cull_count = p_scenario->octree.cull_convex(planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK);
for (int j=0;j<cull_count;j++) {
Instance *instance = instance_shadow_cull_result[j];
if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) {
cull_count--;
SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]);
j--;
}
}
print_line("MOMONGO");
VSG::scene_render->light_instance_set_shadow_transform(light->instance,cm,p_instance->transform,radius,0,0);
VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,0,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count);
} break;
}
}
void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewport_size,RID p_shadow_atlas) {
Camera *camera = camera_owner.getornull(p_camera);
ERR_FAIL_COND(!camera);
@ -1112,8 +1506,10 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
/* STEP 1 - SETUP CAMERA */
CameraMatrix camera_matrix;
Transform camera_inverse_xform = camera->transform.affine_inverse();
bool ortho=false;
switch(camera->type) {
case Camera::ORTHOGONAL: {
@ -1268,12 +1664,14 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
//do not add this light if no geometry is affected by it..
light_cull_result[light_cull_count]=ins;
light_instance_cull_result[light_cull_count]=light->instance;
VSG::scene_render->light_instance_mark_visible(light->instance); //mark it visible for shadow allocation later
if (p_shadow_atlas.is_valid() && VSG::storage->light_has_shadow(ins->base)) {
VSG::scene_render->light_instance_mark_visible(light->instance); //mark it visible for shadow allocation later
}
light_cull_count++;
}
// rasterizer->light_instance_set_active_hint(ins->light_info->instance);
}
} else if ((1<<ins->base_type)&VS::INSTANCE_GEOMETRY_MASK && ins->visible && ins->cast_shadows!=VS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
@ -1386,6 +1784,10 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
// directional lights
{
Instance** lights_with_shadow = (Instance**)alloca(sizeof(Instance*)*light_cull_count);
int directional_shadow_count=0;
for (List<Instance*>::Element *E=scenario->directional_lights.front();E;E=E->next()) {
if (light_cull_count+directional_light_count>=MAX_LIGHTS_CULLED) {
@ -1401,42 +1803,142 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
//check shadow..
/* if (light && light->light_info->enabled && rasterizer->light_has_shadow(light->base_rid)) {
//rasterizer->light_instance_set_active_hint(light->light_info->instance);
_light_instance_update_shadow(light,p_scenario,camera,cull_range);
if (light && VSG::storage->light_has_shadow(E->get()->base)) {
lights_with_shadow[directional_shadow_count++]=E->get();
}
*/
//add to list
directional_light_ptr[directional_light_count++]=light->instance;
}
VSG::scene_render->set_directional_shadow_count(directional_shadow_count);
for(int i=0;i<directional_shadow_count;i++) {
_light_instance_update_shadow(lights_with_shadow[i],camera,p_shadow_atlas,scenario,p_viewport_size);
}
}
#if 0
{ //this should eventually change to
//assign shadows by distance to camera
SortArray<Instance*,_InstanceLightsort> sorter;
sorter.sort(light_cull_result,light_cull_count);
{ //setup shadow maps
//SortArray<Instance*,_InstanceLightsort> sorter;
//sorter.sort(light_cull_result,light_cull_count);
for (int i=0;i<light_cull_count;i++) {
Instance *ins = light_cull_result[i];
if (!rasterizer->light_has_shadow(ins->base_rid) || !shadows_enabled)
if (!p_shadow_atlas.is_valid() || !VSG::storage->light_has_shadow(ins->base))
continue;
/* for far shadows?
if (ins->version == ins->light_info->last_version && rasterizer->light_instance_has_far_shadow(ins->light_info->instance))
continue; // didn't change
*/
InstanceLightData * light = static_cast<InstanceLightData*>(ins->base_data);
float coverage;
{ //compute coverage
Transform cam_xf = camera->transform;
float zn = camera_matrix.get_z_near();
Plane p (cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2) ); //camera near plane
float vp_w,vp_h; //near plane size in screen coordinates
camera_matrix.get_viewport_size(vp_w,vp_h);
switch(VSG::storage->light_get_type(ins->base)) {
case VS::LIGHT_OMNI: {
float radius = VSG::storage->light_get_param(ins->base,VS::LIGHT_PARAM_RANGE);
//get two points parallel to near plane
Vector3 points[2]={
ins->transform.origin,
ins->transform.origin+cam_xf.basis.get_axis(0)*radius
};
if (!ortho) {
//if using perspetive, map them to near plane
for(int j=0;j<2;j++) {
if (p.distance_to(points[j]) < 0 ) {
points[j].z=-zn; //small hack to keep size constant when hitting the screen
}
p.intersects_segment(cam_xf.origin,points[j],&points[j]); //map to plane
}
}
float screen_diameter = points[0].distance_to(points[1])*2;
coverage = screen_diameter / (vp_w+vp_h);
} break;
case VS::LIGHT_SPOT: {
float radius = VSG::storage->light_get_param(ins->base,VS::LIGHT_PARAM_RANGE);
float angle = VSG::storage->light_get_param(ins->base,VS::LIGHT_PARAM_SPOT_ANGLE);
float w = radius*Math::sin(Math::deg2rad(angle));
float d = radius*Math::cos(Math::deg2rad(angle));
Vector3 base = ins->transform.origin-ins->transform.basis.get_axis(2).normalized()*d;
Vector3 points[2]={
base,
base+cam_xf.basis.get_axis(0)*w
};
if (!ortho) {
//if using perspetive, map them to near plane
for(int j=0;j<2;j++) {
if (p.distance_to(points[j]) < 0 ) {
points[j].z=-zn; //small hack to keep size constant when hitting the screen
}
p.intersects_segment(cam_xf.origin,points[j],&points[j]); //map to plane
}
}
float screen_diameter = points[0].distance_to(points[1])*2;
coverage = screen_diameter / (vp_w+vp_h);
} break;
default: {
ERR_PRINT("Invalid Light Type");
}
}
}
if (light->shadow_dirty) {
light->last_version++;
light->shadow_dirty=false;
}
bool redraw = VSG::scene_render->shadow_atlas_update_light(p_shadow_atlas,light->instance,coverage,light->last_version);
if (redraw) {
//must redraw!
_light_instance_update_shadow(ins,camera,p_shadow_atlas,scenario,p_viewport_size);
}
_light_instance_update_shadow(ins,p_scenario,camera,cull_range);
ins->light_info->last_version=ins->version;
}
}
#endif
/* ENVIRONMENT */
RID environment;
@ -1492,7 +1994,8 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewp
VSG::scene_render->render_scene(camera->transform, camera_matrix,ortho,(RasterizerScene::InstanceBase**)instance_cull_result,cull_count,light_instance_cull_result,light_cull_count,directional_light_ptr,directional_light_count,environment);
VSG::scene_render->render_scene(camera->transform, camera_matrix,ortho,(RasterizerScene::InstanceBase**)instance_cull_result,cull_count,light_instance_cull_result,light_cull_count+directional_light_count,environment,p_shadow_atlas);
}
@ -1505,9 +2008,77 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
_update_instance_aabb(p_instance);
if (p_instance->update_materials) {
if (p_instance->base_type==VS::INSTANCE_MESH) {
p_instance->materials.resize(VSG::storage->mesh_get_surface_count(p_instance->base));
//remove materials no longer used and un-own them
int new_mat_count = VSG::storage->mesh_get_surface_count(p_instance->base);
for(int i=p_instance->materials.size()-1;i>=new_mat_count;i--) {
if (p_instance->materials[i].is_valid()) {
VSG::storage->material_remove_instance_owner(p_instance->materials[i],p_instance);
}
}
p_instance->materials.resize(new_mat_count);
}
if ((1<<p_instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData*>(p_instance->base_data);
bool can_cast_shadows=true;
if (p_instance->cast_shadows==VS::SHADOW_CASTING_SETTING_OFF) {
can_cast_shadows=false;
} else if (p_instance->material_override.is_valid()) {
can_cast_shadows=VSG::storage->material_casts_shadows(p_instance->material_override);
} else {
RID mesh;
if (p_instance->base_type==VS::INSTANCE_MESH) {
mesh=p_instance->base;
} else if (p_instance->base_type==VS::INSTANCE_MULTIMESH) {
}
if (mesh.is_valid()) {
bool cast_shadows=false;
for(int i=0;i<p_instance->materials.size();i++) {
RID mat = p_instance->materials[i].is_valid()?p_instance->materials[i]:VSG::storage->mesh_surface_get_material(mesh,i);
if (!mat.is_valid()) {
cast_shadows=true;
break;
}
if (VSG::storage->material_casts_shadows(mat)) {
cast_shadows=true;
break;
}
}
if (!cast_shadows) {
can_cast_shadows=false;
}
}
}
if (can_cast_shadows!=geom->can_cast_shadows) {
//ability to cast shadows change, let lights now
for (List<Instance*>::Element *E=geom->lighting.front();E;E=E->next()) {
InstanceLightData *light = static_cast<InstanceLightData*>(E->get()->base_data);
light->shadow_dirty=true;
}
geom->can_cast_shadows=can_cast_shadows;
}
}
}
_update_instance(p_instance);
@ -1557,6 +2128,7 @@ bool VisualServerScene::free(RID p_rid) {
instance_set_room(p_rid,RID());
instance_set_scenario(p_rid,RID());
instance_set_base(p_rid,RID());
instance_geometry_set_material_override(p_rid,RID());
if (instance->skeleton.is_valid())
instance_attach_skeleton(p_rid,RID());

View file

@ -195,6 +195,7 @@ public:
//aabb stuff
bool update_aabb;
bool update_materials;
SelfList<Instance> update_item;
@ -232,6 +233,11 @@ public:
singleton->_instance_queue_update(this,true,true);
}
virtual void base_material_changed() {
singleton->_instance_queue_update(this,false,true);
}
Instance() : scenario_item(this), update_item(this), room_item(this) {
@ -282,10 +288,12 @@ public:
List<Instance*> lighting;
bool lighting_dirty;
bool can_cast_shadows;
InstanceGeometryData() {
lighting_dirty=false;
can_cast_shadows=true;
}
};
@ -298,18 +306,18 @@ public:
};
RID instance;
uint64_t last_hash;
uint64_t last_version;
List<Instance*>::Element *D; // directional light in scenario
bool shadow_sirty;
bool shadow_dirty;
List<PairInfo> geometries;
InstanceLightData() {
shadow_sirty=true;
shadow_dirty=true;
D=NULL;
last_hash=0;
last_version=0;
}
};
@ -360,8 +368,9 @@ public:
_FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
_FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
_FORCE_INLINE_ void _light_instance_update_shadow(Instance *p_instance,Camera* p_camera,RID p_shadow_atlas,Scenario* p_scenario,Size2 p_viewport_rect);
void render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size);
void render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
void update_dirty_instances();
bool free(RID p_rid);

View file

@ -64,7 +64,7 @@ void VisualServerViewport::_draw_viewport(Viewport *p_viewport) {
if (!p_viewport->disable_3d && p_viewport->camera.is_valid()) {
VSG::scene->render_camera(p_viewport->camera,p_viewport->scenario,p_viewport->size);
VSG::scene->render_camera(p_viewport->camera,p_viewport->scenario,p_viewport->size,p_viewport->shadow_atlas);
}
if (!p_viewport->hide_canvas) {
@ -287,7 +287,8 @@ RID VisualServerViewport::viewport_create() {
viewport->self=rid;
viewport->hide_scenario=false;
viewport->hide_canvas=false;
viewport->render_target=VSG::storage->render_target_create();
viewport->render_target=VSG::storage->render_target_create();
viewport->shadow_atlas=VSG::scene_render->shadow_atlas_create();
return rid;
@ -496,6 +497,27 @@ void VisualServerViewport::viewport_set_canvas_layer(RID p_viewport,RID p_canvas
}
void VisualServerViewport::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;
VSG::scene_render->shadow_atlas_set_size( viewport->shadow_atlas, viewport->shadow_atlas_size);
}
void VisualServerViewport::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);
VSG::scene_render->shadow_atlas_set_quadrant_subdivision( viewport->shadow_atlas, p_quadrant, p_subdiv);
}
bool VisualServerViewport::free(RID p_rid) {
Viewport * viewport = viewport_owner.getornull(p_rid);
@ -504,6 +526,7 @@ bool VisualServerViewport::free(RID p_rid) {
VSG::storage->free( viewport->render_target );
VSG::scene_render->free( viewport->shadow_atlas );
while(viewport->canvas_map.front()) {
viewport_remove_canvas(p_rid,viewport->canvas_map.front()->key());

View file

@ -36,6 +36,9 @@ public:
bool disable_environment;
bool disable_3d;
RID shadow_atlas;
int shadow_atlas_size;
VS::ViewportClearMode clear_mode;
@ -67,6 +70,7 @@ public:
rendered_in_prev_frame=false;
disable_environment=false;
viewport_to_screen=0;
shadow_atlas_size=0;
}
};
@ -129,6 +133,9 @@ public:
void viewport_set_global_canvas_transform(RID p_viewport,const Matrix32& p_transform);
void viewport_set_canvas_layer(RID p_viewport,RID p_canvas,int p_layer);
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 draw_viewports();
bool free(RID p_rid);

View file

@ -1021,7 +1021,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh,PrimitiveType p_primi
break;
}
/* determine wether using 16 or 32 bits indices */
if (array_len>(1<<16)) {
if (array_len>=(1<<16)) {
elem_size=4;
@ -1089,6 +1089,454 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh,PrimitiveType p_primi
}
Array VisualServer::_get_array_from_surface(uint32_t p_format,DVector<uint8_t> p_vertex_data,int p_vertex_len,DVector<uint8_t> p_index_data,int p_index_len) const {
uint32_t offsets[ARRAY_MAX];
int total_elem_size=0;
for (int i=0;i<VS::ARRAY_MAX;i++) {
offsets[i]=0; //reset
if (!(p_format&(1<<i))) // no array
continue;
int elem_size=0;
switch(i) {
case VS::ARRAY_VERTEX: {
if (p_format&ARRAY_FLAG_USE_2D_VERTICES) {
elem_size=2;
} else {
elem_size=3;
}
if (p_format&ARRAY_COMPRESS_VERTEX) {
elem_size*=sizeof(int16_t);
} else {
elem_size*=sizeof(float);
}
} break;
case VS::ARRAY_NORMAL: {
if (p_format&ARRAY_COMPRESS_NORMAL) {
elem_size=sizeof(uint32_t);
} else {
elem_size=sizeof(float)*3;
}
} break;
case VS::ARRAY_TANGENT: {
if (p_format&ARRAY_COMPRESS_TANGENT) {
elem_size=sizeof(uint32_t);
} else {
elem_size=sizeof(float)*4;
}
} break;
case VS::ARRAY_COLOR: {
if (p_format&ARRAY_COMPRESS_COLOR) {
elem_size=sizeof(uint32_t);
} else {
elem_size=sizeof(float)*4;
}
} break;
case VS::ARRAY_TEX_UV: {
if (p_format&ARRAY_COMPRESS_TEX_UV) {
elem_size=sizeof(uint32_t);
} else {
elem_size=sizeof(float)*2;
}
} break;
case VS::ARRAY_TEX_UV2: {
if (p_format&ARRAY_COMPRESS_TEX_UV2) {
elem_size=sizeof(uint32_t);
} else {
elem_size=sizeof(float)*2;
}
} break;
case VS::ARRAY_WEIGHTS: {
if (p_format&ARRAY_COMPRESS_WEIGHTS) {
elem_size=sizeof(uint16_t)*4;
} else {
elem_size=sizeof(float)*4;
}
} break;
case VS::ARRAY_BONES: {
if (p_format&ARRAY_FLAG_USE_16_BIT_BONES) {
elem_size=sizeof(uint32_t);
} else {
elem_size=sizeof(uint16_t)*4;
}
} break;
case VS::ARRAY_INDEX: {
if (p_index_len<=0) {
ERR_PRINT("index_array_len==NO_INDEX_ARRAY");
break;
}
/* determine wether using 16 or 32 bits indices */
if (p_index_len>=(1<<16)) {
elem_size=4;
} else {
elem_size=2;
}
offsets[i]=elem_size;
continue;
} break;
default: {
ERR_FAIL_V( Array() );
}
}
offsets[i]=total_elem_size;
total_elem_size+=elem_size;
}
Array ret;
ret.resize(VS::ARRAY_MAX);
DVector<uint8_t>::Read r = p_vertex_data.read();
for(int i=0;i<VS::ARRAY_MAX;i++) {
if (!(p_format&(1<<i)))
continue;
switch(i) {
case VS::ARRAY_VERTEX: {
if (p_format&ARRAY_FLAG_USE_2D_VERTICES) {
DVector<Vector2> arr_2d;
arr_2d.resize(p_vertex_len);
if (p_format&ARRAY_COMPRESS_VERTEX) {
DVector<Vector2>::Write w = arr_2d.write();
for(int j=0;j<p_vertex_len;j++) {
const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]];
w[j]=Vector2(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1]));
}
} else {
DVector<Vector2>::Write w = arr_2d.write();
for(int j=0;j<p_vertex_len;j++) {
const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
w[j]=Vector2(v[0],v[1]);
}
}
ret[i]=arr_2d;
} else {
DVector<Vector3> arr_3d;
arr_3d.resize(p_vertex_len);
if (p_format&ARRAY_COMPRESS_VERTEX) {
DVector<Vector3>::Write w = arr_3d.write();
for(int j=0;j<p_vertex_len;j++) {
const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]];
w[j]=Vector3(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1]),Math::halfptr_to_float(&v[1]));
}
} else {
DVector<Vector3>::Write w = arr_3d.write();
for(int j=0;j<p_vertex_len;j++) {
const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
w[j]=Vector3(v[0],v[1],v[2]);
}
}
ret[i]=arr_3d;
}
} break;
case VS::ARRAY_NORMAL: {
DVector<Vector3> arr;
arr.resize(p_vertex_len);
if (p_format&ARRAY_COMPRESS_NORMAL) {
DVector<Vector3>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]];
w[j]=Vector3( float(v[0]/255.0)*2.0-1.0, float(v[1]/255.0)*2.0-1.0, float(v[2]/255.0)*2.0-1.0 );
}
} else {
DVector<Vector3>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
w[j]=Vector3(v[0],v[1],v[2]);
}
}
ret[i]=arr;
} break;
case VS::ARRAY_TANGENT: {
DVector<float> arr;
arr.resize(p_vertex_len*4);
if (p_format&ARRAY_COMPRESS_TANGENT) {
DVector<float>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]];
for(int k=0;k<4;k++) {
w[j*4+k]=float(v[k]/255.0)*2.0-1.0;
}
}
} else {
DVector<float>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
for(int k=0;k<4;k++) {
w[j*4+k]=v[k];
}
}
}
ret[i]=arr;
} break;
case VS::ARRAY_COLOR: {
DVector<Color> arr;
arr.resize(p_vertex_len);
if (p_format&ARRAY_COMPRESS_COLOR) {
DVector<Color>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]];
w[j]=Color( float(v[0]/255.0)*2.0-1.0, float(v[1]/255.0)*2.0-1.0, float(v[2]/255.0)*2.0-1.0, float(v[3]/255.0)*2.0-1.0 );
}
} else {
DVector<Color>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
w[j]=Color(v[0],v[1],v[2],v[3]);
}
}
ret[i]=arr;
} break;
case VS::ARRAY_TEX_UV: {
DVector<Vector2> arr;
arr.resize(p_vertex_len);
if (p_format&ARRAY_COMPRESS_TEX_UV) {
DVector<Vector2>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]];
w[j]=Vector2(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1]));
}
} else {
DVector<Vector2>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
w[j]=Vector2(v[0],v[1]);
}
}
ret[i]=arr;
} break;
case VS::ARRAY_TEX_UV2: {
DVector<Vector2> arr;
arr.resize(p_vertex_len);
if (p_format&ARRAY_COMPRESS_TEX_UV2) {
DVector<Vector2>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]];
w[j]=Vector2(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1]));
}
} else {
DVector<Vector2>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
w[j]=Vector2(v[0],v[1]);
}
}
ret[i]=arr;
} break;
case VS::ARRAY_WEIGHTS: {
DVector<float> arr;
arr.resize(p_vertex_len*4);
if (p_format&ARRAY_COMPRESS_WEIGHTS) {
DVector<float>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]];
for(int k=0;k<4;k++) {
w[j*4+k]=float(v[k]/65535.0)*2.0-1.0;
}
}
} else {
DVector<float>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
for(int k=0;k<4;k++) {
w[j*4+k]=v[k];
}
}
}
ret[i]=arr;
} break;
case VS::ARRAY_BONES: {
DVector<int> arr;
arr.resize(p_vertex_len*4);
if (p_format&ARRAY_FLAG_USE_16_BIT_BONES) {
DVector<int>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]];
for(int k=0;k<4;k++) {
w[j*4+k]=v[k];
}
}
} else {
DVector<int>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
const int *v = (const int*)&r[j*total_elem_size+offsets[i]];
for(int k=0;k<4;k++) {
w[j*4+k]=v[k];
}
}
}
ret[i]=arr;
} break;
case VS::ARRAY_INDEX: {
/* determine wether using 16 or 32 bits indices */
DVector<uint8_t>::Read ir = p_index_data.read();
DVector<int> arr;
arr.resize(p_index_len);
if (p_index_len<(1<<16)) {
DVector<int>::Write w = arr.write();
for(int j=0;j<p_index_len;j++) {
const uint16_t *v = (const uint16_t*)&ir[j*2];
w[j]=*v;
}
} else {
DVector<int>::Write w = arr.write();
for(int j=0;j<p_index_len;j++) {
const int *v = (const int*)&ir[j*4];
w[j]=*v;
}
}
ret[i]=arr;
} break;
default: {
ERR_FAIL_V( ret );
}
}
}
return ret;
}
Array VisualServer::mesh_surface_get_arrays(RID p_mesh,int p_surface) const {
DVector<uint8_t> vertex_data = mesh_surface_get_array(p_mesh,p_surface);
ERR_FAIL_COND_V(vertex_data.size()==0,Array());
int vertex_len = mesh_surface_get_array_len(p_mesh,p_surface);
DVector<uint8_t> index_data = mesh_surface_get_index_array(p_mesh,p_surface);
int index_len = mesh_surface_get_array_index_len(p_mesh,p_surface);
uint32_t format = mesh_surface_get_format(p_mesh,p_surface);
return _get_array_from_surface(format,vertex_data,vertex_len,index_data,index_len);
}
void VisualServer::_bind_methods() {

View file

@ -51,6 +51,8 @@ class VisualServer : public Object {
DVector<String> _shader_get_param_list(RID p_shader) const;
void _camera_set_orthogonal(RID p_camera,float p_size,float p_z_near,float p_z_far);
void _canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector<float>& p_margins, const Color& p_modulate=Color(1,1,1));
Array _get_array_from_surface(uint32_t p_format,DVector<uint8_t> p_vertex_data,int p_vertex_len,DVector<uint8_t> p_index_data,int p_index_len) const;
protected:
RID _make_test_cube();
void _free_internal_rids();
@ -258,10 +260,15 @@ public:
virtual DVector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const=0;
virtual DVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const=0;
virtual Array mesh_surface_get_arrays(RID p_mesh,int p_surface) const;
virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const=0;
virtual PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const=0;
virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const=0;
virtual Vector<DVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const=0;
virtual Vector<AABB> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const=0;
virtual void mesh_remove_surface(RID p_mesh,int p_index)=0;
virtual int mesh_get_surface_count(RID p_mesh) const=0;
@ -354,7 +361,6 @@ public:
LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET,
LIGHT_PARAM_SHADOW_SPLIT_4_OFFSET,
LIGHT_PARAM_SHADOW_NORMAL_BIAS,
LIGHT_PARAM_SHADOW_BIAS,
LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,
@ -372,10 +378,25 @@ public:
virtual void light_set_cull_mask(RID p_light,uint32_t p_mask)=0;
virtual void light_set_shader(RID p_light,RID p_shader)=0;
// omni light
enum LightOmniShadowMode {
LIGHT_OMNI_SHADOW_DUAL_PARABOLOID,
LIGHT_OMNI_SHADOW_CUBE,
};
virtual void light_omni_set_shadow_mode(RID p_light,LightOmniShadowMode p_mode)=0;
// omni light
enum LightOmniShadowDetail {
LIGHT_OMNI_SHADOW_DETAIL_VERTICAL,
LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL
};
virtual void light_omni_set_shadow_detail(RID p_light,LightOmniShadowDetail p_detail)=0;
// directional light
enum LightDirectionalShadowMode {
LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL,
LIGHT_DIRECTIONAL_SHADOW_PERSPECTIVE,
LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS,
LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS
};
@ -475,6 +496,9 @@ public:
virtual void viewport_set_global_canvas_transform(RID p_viewport,const Matrix32& p_transform)=0;
virtual void viewport_set_canvas_layer(RID p_viewport,RID p_canvas,int p_layer)=0;
virtual void viewport_set_shadow_atlas_size(RID p_viewport,int p_size)=0;
virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport,int p_quadrant,int p_subdiv)=0;
/* ENVIRONMENT API */

View file

@ -1468,7 +1468,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,con
mr.push_back(a);
}
p_mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,d,mr);
p_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES,d,mr);
if (material.is_valid()) {
p_mesh->surface_set_material(surface, material);

View file

@ -1823,6 +1823,19 @@ void SpatialEditorViewport::_notification(int p_what) {
surface->update();
}
int shadowmap_size = Globals::get_singleton()->get("rendering/shadow_atlas/size");
int atlas_q0 = Globals::get_singleton()->get("rendering/shadow_atlas/quadrant_0_subdiv");
int atlas_q1 = Globals::get_singleton()->get("rendering/shadow_atlas/quadrant_1_subdiv");
int atlas_q2 = Globals::get_singleton()->get("rendering/shadow_atlas/quadrant_2_subdiv");
int atlas_q3 = Globals::get_singleton()->get("rendering/shadow_atlas/quadrant_3_subdiv");
viewport->set_shadow_atlas_size(shadowmap_size);
viewport->set_shadow_atlas_quadrant_subdiv(0,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q0));
viewport->set_shadow_atlas_quadrant_subdiv(1,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q1));
viewport->set_shadow_atlas_quadrant_subdiv(2,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q2));
viewport->set_shadow_atlas_quadrant_subdiv(3,Viewport::ShadowAtlasQuadrantSubdiv(atlas_q3));
}
if (p_what==NOTIFICATION_ENTER_TREE) {
@ -2354,6 +2367,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
c->set_area_as_parent_rect();
viewport = memnew( Viewport );
viewport->set_disable_input(true);
c->add_child(viewport);
surface = memnew( Control );
add_child(surface);

View file

@ -133,7 +133,7 @@ void EditorSpatialGizmo::add_lines(const Vector<Vector3> &p_lines, const Ref<Mat
a[Mesh::ARRAY_COLOR]=color;
mesh->add_surface(Mesh::PRIMITIVE_LINES,a);
mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES,a);
mesh->surface_set_material(0,p_material);
if (p_billboard) {
@ -182,7 +182,7 @@ void EditorSpatialGizmo::add_unscaled_billboard(const Ref<Material>& p_material,
a.resize(Mesh::ARRAY_MAX);
a[Mesh::ARRAY_VERTEX]=vs;
a[Mesh::ARRAY_TEX_UV]=uv;
mesh->add_surface(Mesh::PRIMITIVE_TRIANGLE_FAN,a);
mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLE_FAN,a);
mesh->surface_set_material(0,p_material);
if (true) {
@ -259,7 +259,7 @@ void EditorSpatialGizmo::add_handles(const Vector<Vector3> &p_handles, bool p_bi
}
a[VS::ARRAY_COLOR]=colors;
mesh->add_surface(Mesh::PRIMITIVE_POINTS,a);
mesh->add_surface_from_arrays(Mesh::PRIMITIVE_POINTS,a);
mesh->surface_set_material(0,SpatialEditorGizmos::singleton->handle2_material);
if (p_billboard) {
@ -2321,7 +2321,7 @@ void NavigationMeshSpatialGizmo::redraw() {
Array a;
a.resize(Mesh::ARRAY_MAX);
a[0]=tmeshfaces;
m->add_surface(Mesh::PRIMITIVE_TRIANGLES,a);
m->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES,a);
m->surface_set_material(0,navmesh->is_enabled()?SpatialEditorGizmos::singleton->navmesh_solid_material:SpatialEditorGizmos::singleton->navmesh_solid_material_disabled);
add_mesh(m);
add_collision_segments(lines);
@ -3090,7 +3090,7 @@ SpatialEditorGizmos::SpatialEditorGizmos() {
d.resize(VS::ARRAY_MAX);
d[Mesh::ARRAY_VERTEX]=cursor_points;
d[Mesh::ARRAY_COLOR]=cursor_colors;
pos3d_mesh->add_surface(Mesh::PRIMITIVE_LINES,d);
pos3d_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES,d);
pos3d_mesh->surface_set_material(0,mat);
}
@ -3114,7 +3114,7 @@ SpatialEditorGizmos::SpatialEditorGizmos() {
d.resize(VS::ARRAY_MAX);
d[Mesh::ARRAY_VERTEX] = cursor_points;
d[Mesh::ARRAY_COLOR] = cursor_colors;
listener_line_mesh->add_surface(Mesh::PRIMITIVE_LINES, d);
listener_line_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, d);
listener_line_mesh->surface_set_material(0, mat);
}