work in progress global illumination
This commit is contained in:
parent
22a90e8f2a
commit
075fde7f26
29 changed files with 5222 additions and 964 deletions
|
|
@ -1010,6 +1010,48 @@ void RasterizerSceneGLES3::light_instance_mark_visible(RID p_light_instance) {
|
|||
light_instance->last_scene_pass=scene_pass;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////
|
||||
|
||||
RID RasterizerSceneGLES3::gi_probe_instance_create() {
|
||||
|
||||
GIProbeInstance *gipi = memnew(GIProbeInstance);
|
||||
|
||||
return gi_probe_instance_owner.make_rid(gipi);
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES3::gi_probe_instance_set_light_data(RID p_probe,RID p_data) {
|
||||
|
||||
GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!gipi);
|
||||
gipi->data=p_data;
|
||||
if (p_data.is_valid()) {
|
||||
RasterizerStorageGLES3::GIProbeData *gipd = storage->gi_probe_data_owner.getornull(p_data);
|
||||
ERR_FAIL_COND(!gipd);
|
||||
if (gipd) {
|
||||
gipi->tex_cache=gipd->tex_id;
|
||||
gipi->cell_size_cache.x=1.0/gipd->width;
|
||||
gipi->cell_size_cache.y=1.0/gipd->height;
|
||||
gipi->cell_size_cache.z=1.0/gipd->depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
void RasterizerSceneGLES3::gi_probe_instance_set_transform_to_data(RID p_probe,const Transform& p_xform) {
|
||||
|
||||
GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!gipi);
|
||||
gipi->transform_to_data=p_xform;
|
||||
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES3::gi_probe_instance_set_bounds(RID p_probe,const Vector3& p_bounds) {
|
||||
|
||||
GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!gipi);
|
||||
gipi->bounds=p_bounds;
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
////////////////////////////
|
||||
////////////////////////////
|
||||
|
|
@ -1438,7 +1480,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
|
|||
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES3::_setup_light(RenderList::Element *e) {
|
||||
void RasterizerSceneGLES3::_setup_light(RenderList::Element *e,const Transform& p_view_transform) {
|
||||
|
||||
int omni_indices[16];
|
||||
int omni_count=0;
|
||||
|
|
@ -1509,7 +1551,33 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e) {
|
|||
glUniform1iv(state.scene_shader.get_uniform(SceneShaderGLES3::REFLECTION_INDICES),reflection_count,reflection_indices);
|
||||
}
|
||||
|
||||
int gi_probe_count = e->instance->gi_probe_instances.size();
|
||||
if (gi_probe_count) {
|
||||
const RID * ridp = e->instance->gi_probe_instances.ptr();
|
||||
|
||||
GIProbeInstance *gipi = gi_probe_instance_owner.getptr(ridp[0]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-6);
|
||||
glBindTexture(GL_TEXTURE_3D,gipi->tex_cache);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM1, gipi->transform_to_data * p_view_transform);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS1, gipi->bounds);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE1, gipi->cell_size_cache);
|
||||
if (gi_probe_count>1) {
|
||||
|
||||
GIProbeInstance *gipi2 = gi_probe_instance_owner.getptr(ridp[1]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0+storage->config.max_texture_image_units-7);
|
||||
glBindTexture(GL_TEXTURE_3D,gipi2->tex_cache);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM2, gipi2->transform_to_data * p_view_transform);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS2, gipi2->bounds);
|
||||
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE2, gipi2->cell_size_cache);
|
||||
|
||||
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, true );
|
||||
} else {
|
||||
|
||||
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, false );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1672,11 +1740,15 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
|
|||
state.scene_shader.set_conditional(SceneShaderGLES3::LIGHT_USE_PSSM_BLEND,false);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5,false);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13,false);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES,false);
|
||||
|
||||
|
||||
|
||||
//state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,true);
|
||||
} else {
|
||||
|
||||
state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES,e->instance->gi_probe_instances.size()>0);
|
||||
|
||||
state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES3::USE_FORWARD_LIGHTING,!p_directional_add);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES3::USE_LIGHT_DIRECTIONAL,false);
|
||||
|
|
@ -1711,9 +1783,12 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
rebind=true;
|
||||
}
|
||||
|
||||
|
||||
if (p_alpha_pass || p_directional_add) {
|
||||
int desired_blend_mode;
|
||||
if (p_directional_add) {
|
||||
|
|
@ -1794,7 +1869,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
|
|||
}
|
||||
|
||||
if (!(e->sort_key&RenderList::SORT_KEY_UNSHADED_FLAG) && !p_directional_add && !p_shadow) {
|
||||
_setup_light(e);
|
||||
_setup_light(e,p_view_transform);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1837,6 +1913,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements,int p_e
|
|||
state.scene_shader.set_conditional(SceneShaderGLES3::SHADELESS,false);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_5,false);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES3::SHADOW_MODE_PCF_13,false);
|
||||
state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES,false);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1950,6 +2027,10 @@ void RasterizerSceneGLES3::_add_geometry( RasterizerStorageGLES3::Geometry* p_g
|
|||
|
||||
copymem(oe,e,sizeof(RenderList::Element));
|
||||
}
|
||||
|
||||
if (e->instance->gi_probe_instances.size()) {
|
||||
e->sort_key|=RenderList::SORT_KEY_GI_PROBES_FLAG;
|
||||
}
|
||||
}
|
||||
|
||||
//if (e->geometry->type==RasterizerStorageGLES3::Geometry::GEOMETRY_MULTISURFACE)
|
||||
|
|
|
|||
|
|
@ -526,6 +526,25 @@ public:
|
|||
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);
|
||||
|
||||
/* REFLECTION INSTANCE */
|
||||
|
||||
struct GIProbeInstance : public RID_Data {
|
||||
RID data;
|
||||
GLuint tex_cache;
|
||||
Vector3 cell_size_cache;
|
||||
Vector3 bounds;
|
||||
Transform transform_to_data;
|
||||
};
|
||||
|
||||
|
||||
|
||||
mutable RID_Owner<GIProbeInstance> gi_probe_instance_owner;
|
||||
|
||||
virtual RID gi_probe_instance_create();
|
||||
virtual void gi_probe_instance_set_light_data(RID p_probe,RID p_data);
|
||||
virtual void gi_probe_instance_set_transform_to_data(RID p_probe,const Transform& p_xform);
|
||||
virtual void gi_probe_instance_set_bounds(RID p_probe,const Vector3& p_bounds);
|
||||
|
||||
/* RENDER LIST */
|
||||
|
||||
struct RenderList {
|
||||
|
|
@ -541,8 +560,9 @@ public:
|
|||
SORT_KEY_DEPTH_LAYER_SHIFT=60,
|
||||
SORT_KEY_UNSHADED_FLAG=uint64_t(1)<<59,
|
||||
SORT_KEY_NO_DIRECTIONAL_FLAG=uint64_t(1)<<58,
|
||||
SORT_KEY_SHADING_SHIFT=58,
|
||||
SORT_KEY_SHADING_MASK=3,
|
||||
SORT_KEY_GI_PROBES_FLAG=uint64_t(1)<<57,
|
||||
SORT_KEY_SHADING_SHIFT=57,
|
||||
SORT_KEY_SHADING_MASK=7,
|
||||
SORT_KEY_MATERIAL_INDEX_SHIFT=40,
|
||||
SORT_KEY_GEOMETRY_INDEX_SHIFT=20,
|
||||
SORT_KEY_GEOMETRY_TYPE_SHIFT=15,
|
||||
|
|
@ -669,7 +689,7 @@ public:
|
|||
_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(RenderList::Element *e);
|
||||
_FORCE_INLINE_ void _setup_light(RenderList::Element *e,const Transform& p_view_transform);
|
||||
|
||||
void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform& p_view_transform, const CameraMatrix& p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows);
|
||||
|
||||
|
|
|
|||
|
|
@ -1514,6 +1514,7 @@ void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const {
|
|||
p_shader->valid=true;
|
||||
p_shader->version++;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::update_dirty_shaders() {
|
||||
|
|
@ -3600,16 +3601,15 @@ void RasterizerStorageGLES3::multimesh_instance_set_color(RID p_multimesh,int p_
|
|||
ERR_FAIL_COND(multimesh->color_format==VS::MULTIMESH_COLOR_NONE);
|
||||
|
||||
int stride = multimesh->color_floats+multimesh->xform_floats;
|
||||
float *dataptr=&multimesh->data[stride*p_index+multimesh->color_floats];
|
||||
float *dataptr=&multimesh->data[stride*p_index+multimesh->xform_floats];
|
||||
|
||||
if (multimesh->color_format==VS::MULTIMESH_COLOR_8BIT) {
|
||||
union {
|
||||
uint32_t colu;
|
||||
float colf;
|
||||
} cu;
|
||||
|
||||
cu.colu=p_color.to_32();
|
||||
dataptr[ 0]=cu.colf;
|
||||
uint8_t *data8=(uint8_t*)dataptr;
|
||||
data8[0]=CLAMP(p_color.r*255.0,0,255);
|
||||
data8[1]=CLAMP(p_color.g*255.0,0,255);
|
||||
data8[2]=CLAMP(p_color.b*255.0,0,255);
|
||||
data8[3]=CLAMP(p_color.a*255.0,0,255);
|
||||
|
||||
} else if (multimesh->color_format==VS::MULTIMESH_COLOR_FLOAT) {
|
||||
dataptr[ 0]=p_color.r;
|
||||
|
|
@ -3701,7 +3701,7 @@ Color RasterizerStorageGLES3::multimesh_instance_get_color(RID p_multimesh,int p
|
|||
float colf;
|
||||
} cu;
|
||||
|
||||
return Color::hex(cu.colu);
|
||||
return Color::hex(BSWAP32(cu.colu));
|
||||
|
||||
} else if (multimesh->color_format==VS::MULTIMESH_COLOR_FLOAT) {
|
||||
Color c;
|
||||
|
|
@ -4385,6 +4385,15 @@ float RasterizerStorageGLES3::light_get_param(RID p_light,VS::LightParam p_param
|
|||
return light->param[p_param];
|
||||
}
|
||||
|
||||
Color RasterizerStorageGLES3::light_get_color(RID p_light) {
|
||||
|
||||
const Light * light = light_owner.getornull(p_light);
|
||||
ERR_FAIL_COND_V(!light,Color());
|
||||
|
||||
return light->color;
|
||||
|
||||
}
|
||||
|
||||
bool RasterizerStorageGLES3::light_has_shadow(RID p_light) const {
|
||||
|
||||
const Light * light = light_owner.getornull(p_light);
|
||||
|
|
@ -4668,6 +4677,261 @@ void RasterizerStorageGLES3::portal_set_disabled_color(RID p_portal, const Color
|
|||
|
||||
}
|
||||
|
||||
RID RasterizerStorageGLES3::gi_probe_create() {
|
||||
|
||||
GIProbe *gip = memnew( GIProbe );
|
||||
|
||||
gip->data_width=0;
|
||||
gip->data_height=0;
|
||||
gip->data_depth=0;
|
||||
gip->bounds=AABB(Vector3(),Vector3(1,1,1));
|
||||
gip->dynamic_range=1.0;
|
||||
gip->version=1;
|
||||
gip->cell_size=1.0;
|
||||
|
||||
return gi_probe_owner.make_rid(gip);
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::gi_probe_set_bounds(RID p_probe,const AABB& p_bounds){
|
||||
|
||||
GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!gip);
|
||||
|
||||
gip->bounds=p_bounds;
|
||||
gip->version++;
|
||||
gip->instance_change_notify();
|
||||
}
|
||||
AABB RasterizerStorageGLES3::gi_probe_get_bounds(RID p_probe) const{
|
||||
|
||||
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!gip,AABB());
|
||||
|
||||
return gip->bounds;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::gi_probe_set_cell_size(RID p_probe,float p_size) {
|
||||
|
||||
GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!gip);
|
||||
|
||||
gip->cell_size=p_size;
|
||||
gip->version++;
|
||||
gip->instance_change_notify();
|
||||
}
|
||||
|
||||
float RasterizerStorageGLES3::gi_probe_get_cell_size(RID p_probe) const {
|
||||
|
||||
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!gip,0);
|
||||
|
||||
return gip->cell_size;
|
||||
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::gi_probe_set_to_cell_xform(RID p_probe,const Transform& p_xform) {
|
||||
|
||||
GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!gip);
|
||||
|
||||
gip->to_cell=p_xform;
|
||||
}
|
||||
|
||||
Transform RasterizerStorageGLES3::gi_probe_get_to_cell_xform(RID p_probe) const {
|
||||
|
||||
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!gip,Transform());
|
||||
|
||||
return gip->to_cell;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void RasterizerStorageGLES3::gi_probe_set_dynamic_data(RID p_probe,const DVector<int>& p_data){
|
||||
GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!gip);
|
||||
|
||||
gip->dynamic_data=p_data;
|
||||
gip->version++;
|
||||
gip->instance_change_notify();
|
||||
|
||||
}
|
||||
DVector<int> RasterizerStorageGLES3::gi_probe_get_dynamic_data(RID p_probe) const{
|
||||
|
||||
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!gip,DVector<int>());
|
||||
|
||||
return gip->dynamic_data;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::gi_probe_set_dynamic_range(RID p_probe,float p_range){
|
||||
|
||||
GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND(!gip);
|
||||
|
||||
gip->dynamic_range=p_range;
|
||||
|
||||
}
|
||||
float RasterizerStorageGLES3::gi_probe_get_dynamic_range(RID p_probe) const{
|
||||
|
||||
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!gip,0);
|
||||
|
||||
return gip->dynamic_range;
|
||||
}
|
||||
|
||||
|
||||
void RasterizerStorageGLES3::gi_probe_set_static_data(RID p_gi_probe,const DVector<uint8_t>& p_data,VS::GIProbeDataFormat p_format,int p_width,int p_height,int p_depth) {
|
||||
|
||||
GIProbe *gip = gi_probe_owner.getornull(p_gi_probe);
|
||||
ERR_FAIL_COND(!gip);
|
||||
|
||||
if (gip->data.is_valid()) {
|
||||
free(gip->data);
|
||||
}
|
||||
|
||||
gip->data=RID();
|
||||
//this is platform dependent
|
||||
|
||||
gip->version++;
|
||||
gip->instance_change_notify();
|
||||
|
||||
}
|
||||
DVector<uint8_t> RasterizerStorageGLES3::gi_probe_get_static_data(RID p_gi_probe) const {
|
||||
|
||||
const GIProbe *gip = gi_probe_owner.getornull(p_gi_probe);
|
||||
ERR_FAIL_COND_V(!gip,DVector<uint8_t>());
|
||||
|
||||
//platform dependent
|
||||
return DVector<uint8_t>();
|
||||
}
|
||||
VS::GIProbeDataFormat RasterizerStorageGLES3::gi_probe_get_static_data_format(RID p_gi_probe) const {
|
||||
|
||||
const GIProbe *gip = gi_probe_owner.getornull(p_gi_probe);
|
||||
ERR_FAIL_COND_V(!gip,VS::GI_PROBE_DATA_RGBA8);
|
||||
|
||||
return gip->data_format;
|
||||
}
|
||||
int RasterizerStorageGLES3::gi_probe_get_static_data_width(RID p_probe) const {
|
||||
|
||||
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!gip,0);
|
||||
|
||||
return gip->data_width;
|
||||
}
|
||||
int RasterizerStorageGLES3::gi_probe_get_static_data_height(RID p_probe) const {
|
||||
|
||||
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!gip,0);
|
||||
return gip->data_height;
|
||||
}
|
||||
int RasterizerStorageGLES3::gi_probe_get_static_data_depth(RID p_probe) const {
|
||||
|
||||
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!gip,0);
|
||||
return gip->data_depth;
|
||||
}
|
||||
|
||||
RID RasterizerStorageGLES3::gi_probe_get_data(RID p_probe) {
|
||||
|
||||
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!gip,RID());
|
||||
|
||||
return gip->data;
|
||||
}
|
||||
|
||||
uint32_t RasterizerStorageGLES3::gi_probe_get_version(RID p_probe) {
|
||||
|
||||
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
|
||||
ERR_FAIL_COND_V(!gip,0);
|
||||
|
||||
return gip->version;
|
||||
}
|
||||
|
||||
RID RasterizerStorageGLES3::gi_probe_dynamic_data_create(int p_width,int p_height,int p_depth) {
|
||||
|
||||
GIProbeData *gipd = memnew( GIProbeData );
|
||||
|
||||
gipd->width=p_width;
|
||||
gipd->height=p_height;
|
||||
gipd->depth=p_depth;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glGenTextures(1,&gipd->tex_id);
|
||||
glBindTexture(GL_TEXTURE_3D,gipd->tex_id);
|
||||
|
||||
int level=0;
|
||||
|
||||
print_line("dyndata create");
|
||||
while(true) {
|
||||
|
||||
Vector<uint8_t> data;
|
||||
data.resize(p_width*p_height*p_depth*4);
|
||||
|
||||
|
||||
for(int i=0;i<data.size();i+=4) {
|
||||
|
||||
data[i+0]=0xFF;
|
||||
data[i+1]=0x00;
|
||||
data[i+2]=0xFF;
|
||||
data[i+3]=0xFF;
|
||||
}
|
||||
|
||||
glTexImage3D(GL_TEXTURE_3D,level,GL_RGBA8,p_width,p_height,p_depth,0,GL_RGBA,GL_UNSIGNED_BYTE,data.ptr());
|
||||
if (p_width<=1 || p_height<=1 || p_depth<=1)
|
||||
break;
|
||||
p_width>>=1;
|
||||
p_height>>=1;
|
||||
p_depth>>=1;
|
||||
level++;
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, level);
|
||||
|
||||
gipd->levels=level+1;
|
||||
|
||||
return gi_probe_data_owner.make_rid(gipd);
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::gi_probe_dynamic_data_update_rgba8(RID p_gi_probe_data, int p_depth_slice, int p_slice_count, int p_mipmap, const void *p_data) {
|
||||
|
||||
GIProbeData *gipd = gi_probe_data_owner.getornull(p_gi_probe_data);
|
||||
ERR_FAIL_COND(!gipd);
|
||||
/*
|
||||
Vector<uint8_t> data;
|
||||
data.resize((gipd->width>>p_mipmap)*(gipd->height>>p_mipmap)*(gipd->depth>>p_mipmap)*4);
|
||||
|
||||
for(int i=0;i<(gipd->width>>p_mipmap);i++) {
|
||||
for(int j=0;j<(gipd->height>>p_mipmap);j++) {
|
||||
for(int k=0;k<(gipd->depth>>p_mipmap);k++) {
|
||||
|
||||
int ofs = (k*(gipd->height>>p_mipmap)*(gipd->width>>p_mipmap)) + j *(gipd->width>>p_mipmap) + i;
|
||||
ofs*=4;
|
||||
data[ofs+0]=i*0xFF/(gipd->width>>p_mipmap);
|
||||
data[ofs+1]=j*0xFF/(gipd->height>>p_mipmap);
|
||||
data[ofs+2]=k*0xFF/(gipd->depth>>p_mipmap);
|
||||
data[ofs+3]=0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_3D,gipd->tex_id);
|
||||
glTexSubImage3D(GL_TEXTURE_3D,p_mipmap,0,0,p_depth_slice,gipd->width>>p_mipmap,gipd->height>>p_mipmap,p_slice_count,GL_RGBA,GL_UNSIGNED_BYTE,p_data);
|
||||
//glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,p_data);
|
||||
//glTexImage3D(GL_TEXTURE_3D,p_mipmap,GL_RGBA8,gipd->width>>p_mipmap,gipd->height>>p_mipmap,gipd->depth>>p_mipmap,0,GL_RGBA,GL_UNSIGNED_BYTE,data.ptr());
|
||||
print_line("update rgba8 "+itos(p_mipmap));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance) {
|
||||
|
||||
Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);
|
||||
|
|
@ -4709,6 +4973,10 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene:
|
|||
inst = light_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
case VS::INSTANCE_GI_PROBE: {
|
||||
inst = gi_probe_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
default: {
|
||||
if (!inst) {
|
||||
ERR_FAIL();
|
||||
|
|
@ -4744,6 +5012,10 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce
|
|||
inst = light_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
case VS::INSTANCE_GI_PROBE: {
|
||||
inst = gi_probe_owner.getornull(p_base);
|
||||
ERR_FAIL_COND(!inst);
|
||||
} break;
|
||||
default: {
|
||||
|
||||
if (!inst) {
|
||||
|
|
@ -5395,19 +5667,27 @@ VS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const {
|
|||
if (mesh_owner.owns(p_rid)) {
|
||||
return VS::INSTANCE_MESH;
|
||||
}
|
||||
|
||||
if (multimesh_owner.owns(p_rid)) {
|
||||
return VS::INSTANCE_MULTIMESH;
|
||||
}
|
||||
|
||||
if (immediate_owner.owns(p_rid)) {
|
||||
return VS::INSTANCE_IMMEDIATE;
|
||||
}
|
||||
|
||||
if (light_owner.owns(p_rid)) {
|
||||
return VS::INSTANCE_LIGHT;
|
||||
}
|
||||
|
||||
if (reflection_probe_owner.owns(p_rid)) {
|
||||
return VS::INSTANCE_REFLECTION_PROBE;
|
||||
}
|
||||
|
||||
if (gi_probe_owner.owns(p_rid)) {
|
||||
return VS::INSTANCE_GI_PROBE;
|
||||
}
|
||||
|
||||
return VS::INSTANCE_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -5561,6 +5841,27 @@ bool RasterizerStorageGLES3::free(RID p_rid){
|
|||
reflection_probe_owner.free(p_rid);
|
||||
memdelete(reflection_probe);
|
||||
|
||||
} else if (gi_probe_owner.owns(p_rid)) {
|
||||
|
||||
// delete the texture
|
||||
GIProbe *gi_probe = gi_probe_owner.get(p_rid);
|
||||
|
||||
if (gi_probe->data.is_valid()) {
|
||||
free(gi_probe->data);
|
||||
}
|
||||
|
||||
gi_probe_owner.free(p_rid);
|
||||
memdelete(gi_probe);
|
||||
} else if (gi_probe_data_owner.owns(p_rid)) {
|
||||
|
||||
// delete the texture
|
||||
GIProbeData *gi_probe_data = gi_probe_data_owner.get(p_rid);
|
||||
|
||||
print_line("dyndata delete");
|
||||
glDeleteTextures(1,&gi_probe_data->tex_id);
|
||||
gi_probe_owner.free(p_rid);
|
||||
memdelete(gi_probe_data);
|
||||
|
||||
} else if (canvas_occluder_owner.owns(p_rid)) {
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -799,6 +799,7 @@ public:
|
|||
|
||||
virtual VS::LightType light_get_type(RID p_light) const;
|
||||
virtual float light_get_param(RID p_light,VS::LightParam p_param);
|
||||
virtual Color light_get_color(RID p_light);
|
||||
|
||||
virtual AABB light_get_aabb(RID p_light) const;
|
||||
virtual uint64_t light_get_version(RID p_light) const;
|
||||
|
|
@ -868,6 +869,84 @@ public:
|
|||
virtual void portal_set_disable_distance(RID p_portal, float p_distance);
|
||||
virtual void portal_set_disabled_color(RID p_portal, const Color& p_color);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* GI PROBE API */
|
||||
|
||||
struct GIProbe : public Instantiable {
|
||||
|
||||
|
||||
AABB bounds;
|
||||
Transform to_cell;
|
||||
float cell_size;
|
||||
|
||||
float dynamic_range;
|
||||
|
||||
uint32_t version;
|
||||
|
||||
DVector<int> dynamic_data;
|
||||
|
||||
RID data;
|
||||
int data_width;
|
||||
int data_height;
|
||||
int data_depth;
|
||||
VS::GIProbeDataFormat data_format;
|
||||
|
||||
|
||||
};
|
||||
|
||||
mutable RID_Owner<GIProbe> gi_probe_owner;
|
||||
|
||||
virtual RID gi_probe_create();
|
||||
|
||||
virtual void gi_probe_set_bounds(RID p_probe,const AABB& p_bounds);
|
||||
virtual AABB gi_probe_get_bounds(RID p_probe) const;
|
||||
|
||||
virtual void gi_probe_set_cell_size(RID p_probe, float p_size);
|
||||
virtual float gi_probe_get_cell_size(RID p_probe) const;
|
||||
|
||||
virtual void gi_probe_set_to_cell_xform(RID p_probe,const Transform& p_xform);
|
||||
virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const;
|
||||
|
||||
virtual void gi_probe_set_dynamic_data(RID p_probe,const DVector<int>& p_data);
|
||||
virtual DVector<int> gi_probe_get_dynamic_data(RID p_probe) const;
|
||||
|
||||
virtual void gi_probe_set_dynamic_range(RID p_probe,float p_range);
|
||||
virtual float gi_probe_get_dynamic_range(RID p_probe) const;
|
||||
|
||||
|
||||
virtual void gi_probe_set_static_data(RID p_gi_probe,const DVector<uint8_t>& p_data,VS::GIProbeDataFormat p_format,int p_width,int p_height,int p_depth);
|
||||
virtual DVector<uint8_t> gi_probe_get_static_data(RID p_gi_probe) const;
|
||||
virtual VS::GIProbeDataFormat gi_probe_get_static_data_format(RID p_gi_probe) const;
|
||||
virtual int gi_probe_get_static_data_width(RID p_probe) const;
|
||||
virtual int gi_probe_get_static_data_height(RID p_probe) const;
|
||||
virtual int gi_probe_get_static_data_depth(RID p_probe) const;
|
||||
|
||||
virtual RID gi_probe_get_data(RID p_probe); //get data in case this is static
|
||||
virtual uint32_t gi_probe_get_version(RID p_probe);
|
||||
|
||||
struct GIProbeData : public RID_Data {
|
||||
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
int levels;
|
||||
GLuint tex_id;
|
||||
|
||||
GIProbeData() {
|
||||
}
|
||||
};
|
||||
|
||||
mutable RID_Owner<GIProbeData> gi_probe_data_owner;
|
||||
|
||||
virtual RID gi_probe_dynamic_data_create(int p_width,int p_height,int p_depth);
|
||||
virtual void gi_probe_dynamic_data_update_rgba8(RID p_gi_probe_data,int p_depth_slice,int p_slice_count,int p_mipmap,const void* p_data);
|
||||
|
||||
|
||||
virtual void instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance);
|
||||
virtual void instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance);
|
||||
|
||||
|
|
|
|||
|
|
@ -838,6 +838,131 @@ void reflection_process(int idx, vec3 vertex, vec3 normal,vec3 binormal, vec3 ta
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef USE_GI_PROBES
|
||||
|
||||
uniform mediump sampler3D gi_probe1; //texunit:-6
|
||||
uniform highp mat4 gi_probe_xform1;
|
||||
uniform highp vec3 gi_probe_bounds1;
|
||||
uniform highp vec3 gi_probe_cell_size1;
|
||||
|
||||
uniform mediump sampler3D gi_probe2; //texunit:-7
|
||||
uniform highp mat4 gi_probe_xform2;
|
||||
uniform highp vec3 gi_probe_bounds2;
|
||||
uniform highp vec3 gi_probe_cell_size2;
|
||||
uniform bool gi_probe2_enabled;
|
||||
|
||||
vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance) {
|
||||
|
||||
|
||||
float dist = dot(direction,mix(vec3(-1.0),vec3(1.0),greaterThan(direction,vec3(0.0))))*2.0;
|
||||
float alpha=0.0;
|
||||
vec4 color = vec4(0.0);
|
||||
|
||||
while(dist < max_distance && alpha < 0.95) {
|
||||
float diameter = max(1.0, 2.0 * tan_half_angle * dist);
|
||||
vec4 scolor = textureLod(probe, (pos + dist * direction) * cell_size, log2(diameter) );
|
||||
float a = (1.0 - alpha);
|
||||
color.rgb += a * scolor.rgb;
|
||||
alpha += a * scolor.a;
|
||||
dist += diameter * 0.5;
|
||||
}
|
||||
|
||||
return color.rgb;
|
||||
}
|
||||
|
||||
void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_size,vec3 pos, mat3 normal_mtx,vec3 ref_vec, float roughness, out vec4 out_spec, out vec4 out_diff) {
|
||||
|
||||
|
||||
|
||||
vec3 probe_pos = (probe_xform * vec4(pos,1.0)).xyz;
|
||||
vec3 ref_pos = (probe_xform * vec4(pos+ref_vec,1.0)).xyz;
|
||||
|
||||
ref_vec = normalize(ref_pos - probe_pos);
|
||||
|
||||
/* out_diff.rgb = voxel_cone_trace(probe,cell_size,probe_pos,normalize((probe_xform * vec4(ref_vec,0.0)).xyz),0.0 ,100.0);
|
||||
out_diff.a = 1.0;
|
||||
return;*/
|
||||
//out_diff = vec4(textureLod(probe,probe_pos*cell_size,3.0).rgb,1.0);
|
||||
//return;
|
||||
|
||||
if (any(bvec2(any(lessThan(probe_pos,vec3(0.0))),any(greaterThan(probe_pos,bounds)))))
|
||||
return;
|
||||
|
||||
vec3 blendv = probe_pos/bounds * 2.0 - 1.0;
|
||||
float blend = 1.001-max(blendv.x,max(blendv.y,blendv.z));
|
||||
blend=1.0;
|
||||
|
||||
//radiance
|
||||
|
||||
#define MAX_CONE_DIRS 6
|
||||
vec3 cone_dirs[MAX_CONE_DIRS] = vec3[] (
|
||||
vec3(0, 0, 1),
|
||||
vec3(0.866025, 0, 0.5),
|
||||
vec3(0.267617, 0.823639, 0.5),
|
||||
vec3(-0.700629, 0.509037, 0.5),
|
||||
vec3(-0.700629, -0.509037, 0.5),
|
||||
vec3(0.267617, -0.823639, 0.5)
|
||||
);
|
||||
|
||||
float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15);
|
||||
|
||||
float max_distance = length(bounds);
|
||||
vec3 light=vec3(0.0);
|
||||
for(int i=0;i<MAX_CONE_DIRS;i++) {
|
||||
|
||||
vec3 dir = normalize( (probe_xform * vec4(pos + normal_mtx * cone_dirs[i],1.0)).xyz - probe_pos);
|
||||
light+=cone_weights[i] * voxel_cone_trace(probe,cell_size,probe_pos,dir,0.577,max_distance);
|
||||
|
||||
}
|
||||
|
||||
out_diff = vec4(light*blend,blend);
|
||||
|
||||
//irradiance
|
||||
|
||||
vec3 irr_light = voxel_cone_trace(probe,cell_size,probe_pos,ref_vec,tan(roughness * 0.5 * M_PI) ,max_distance);
|
||||
//irr_light=vec3(0.0);
|
||||
|
||||
out_spec = vec4(irr_light*blend,blend);
|
||||
}
|
||||
|
||||
|
||||
void gi_probes_compute(vec3 pos, vec3 normal, float roughness, vec3 specular, inout vec3 out_specular, inout vec3 out_ambient) {
|
||||
|
||||
|
||||
vec3 ref_vec = normalize(reflect(normalize(pos),normal));
|
||||
|
||||
//find arbitrary tangent and bitangent, then build a matrix
|
||||
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0, 0, 1) : vec3(0, 1, 0);
|
||||
vec3 tangent = normalize(cross(v0, normal));
|
||||
vec3 bitangent = normalize(cross(tangent, normal));
|
||||
mat3 normal_mat = mat3(tangent,bitangent,normal);
|
||||
|
||||
vec4 diff_accum = vec4(0.0);
|
||||
vec4 spec_accum = vec4(0.0);
|
||||
|
||||
gi_probe_compute(gi_probe1,gi_probe_xform1,gi_probe_bounds1,gi_probe_cell_size1,pos,normal_mat,ref_vec,roughness,spec_accum,diff_accum);
|
||||
|
||||
if (gi_probe2_enabled) {
|
||||
|
||||
gi_probe_compute(gi_probe2,gi_probe_xform2,gi_probe_bounds2,gi_probe_cell_size2,pos,normal_mat,ref_vec,roughness,spec_accum,diff_accum);
|
||||
}
|
||||
|
||||
if (diff_accum.a>0.0) {
|
||||
diff_accum.rgb/=diff_accum.a;
|
||||
}
|
||||
|
||||
if (spec_accum.a>0.0) {
|
||||
spec_accum.rgb/=spec_accum.a;
|
||||
}
|
||||
|
||||
out_specular+=spec_accum.rgb;
|
||||
out_ambient+=diff_accum.rgb;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void main() {
|
||||
|
||||
#ifdef RENDER_SHADOW_DUAL_PARABOLOID
|
||||
|
|
@ -1161,21 +1286,27 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
#endif //#USE_LIGHT_DIRECTIONAL
|
||||
|
||||
#ifdef USE_GI_PROBES
|
||||
gi_probes_compute(vertex,normal,roughness,specular,specular_light,ambient_light);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_FORWARD_LIGHTING
|
||||
|
||||
highp vec4 reflection_accum = vec4(0.0,0.0,0.0,0.0);
|
||||
highp vec4 ambient_accum = vec4(0.0,0.0,0.0,0.0);
|
||||
|
||||
|
||||
|
||||
for(int i=0;i<reflection_count;i++) {
|
||||
reflection_process(reflection_indices[i],vertex,normal,binormal,tangent,roughness,anisotropy,ambient_light,specular_light,brdf,reflection_accum,ambient_accum);
|
||||
}
|
||||
|
||||
if (reflection_accum.a>0.0) {
|
||||
specular_light=reflection_accum.rgb/reflection_accum.a;
|
||||
specular_light+=reflection_accum.rgb/reflection_accum.a;
|
||||
}
|
||||
if (ambient_accum.a>0.0) {
|
||||
ambient_light=ambient_accum.rgb/ambient_accum.a;
|
||||
ambient_light+=ambient_accum.rgb/ambient_accum.a;
|
||||
}
|
||||
|
||||
for(int i=0;i<omni_light_count;i++) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue