can bake for omni and spotlight

store normal when baking
This commit is contained in:
Juan Linietsky 2016-12-22 10:00:15 -03:00
parent 37f558cd7b
commit f9603d8236
14 changed files with 440 additions and 92 deletions

View file

@ -130,9 +130,9 @@ void RasterizerGLES3::initialize() {
ERR_PRINT("Error initializing GLAD");
}
// glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
// glDebugMessageCallbackARB(_gl_debug_print, NULL);
// glEnable(_EXT_DEBUG_OUTPUT);
glEnable(_EXT_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
glDebugMessageCallbackARB(_gl_debug_print, NULL);
glEnable(_EXT_DEBUG_OUTPUT);
#endif

View file

@ -100,6 +100,8 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas,int p_size){
shadow_atlas->depth=0;
shadow_atlas->fbo=0;
print_line("erasing atlas");
}
for(int i=0;i<4;i++) {
//clear subdivisions
@ -130,19 +132,18 @@ void RasterizerSceneGLES3::shadow_atlas_set_size(RID p_atlas,int p_size){
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, shadow_atlas->size, shadow_atlas->size, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
//interpola nearest (though nvidia can improve this)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Remove artifact on the edges of the shadowmap
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// We'll use a depth texture to store the depths in the shadow map
// Attach the depth texture to FBO depth attachment point
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D, shadow_atlas->depth, 0);
glViewport(0,0,shadow_atlas->size,shadow_atlas->size);
glClearDepth(0);
glClear(GL_DEPTH_BUFFER_BIT);
}
}
@ -523,12 +524,19 @@ void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas,int p_size)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5);
mmsize=reflection_atlas->size;
for(int i=0;i<6;i++) {
glGenFramebuffers(1, &reflection_atlas->fbo[i]);
glBindFramebuffer(GL_FRAMEBUFFER, reflection_atlas->fbo[i]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, reflection_atlas->color, i);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
ERR_CONTINUE(status!=GL_FRAMEBUFFER_COMPLETE);
glDisable(GL_SCISSOR_TEST);
glViewport(0,0,mmsize,mmsize);
glClearColor(0,0,0,0);
@ -538,8 +546,6 @@ void RasterizerSceneGLES3::reflection_atlas_set_size(RID p_ref_atlas,int p_size)
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5);
}
@ -1020,11 +1026,12 @@ RID RasterizerSceneGLES3::gi_probe_instance_create() {
return gi_probe_instance_owner.make_rid(gipi);
}
void RasterizerSceneGLES3::gi_probe_instance_set_light_data(RID p_probe,RID p_data) {
void RasterizerSceneGLES3::gi_probe_instance_set_light_data(RID p_probe, RID p_base, RID p_data) {
GIProbeInstance *gipi = gi_probe_instance_owner.getornull(p_probe);
ERR_FAIL_COND(!gipi);
gipi->data=p_data;
gipi->probe=storage->gi_probe_owner.getornull(p_base);
if (p_data.is_valid()) {
RasterizerStorageGLES3::GIProbeData *gipd = storage->gi_probe_data_owner.getornull(p_data);
ERR_FAIL_COND(!gipd);
@ -1571,6 +1578,8 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e,const Transform&
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_MULTIPLIER1, gipi->probe?gipi->probe->dynamic_range*gipi->probe->energy:0.0);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BLEND_AMBIENT1, gipi->probe?!gipi->probe->interior:false);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_CELL_SIZE1, gipi->cell_size_cache);
if (gi_probe_count>1) {
@ -1581,7 +1590,8 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e,const Transform&
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_PROBE_MULTIPLIER2, gipi2->probe?gipi2->probe->dynamic_range*gipi2->probe->energy:0.0);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BLEND_AMBIENT2, gipi2->probe?!gipi2->probe->interior:false);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE2_ENABLED, true );
} else {
@ -4209,7 +4219,6 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa
fbo=shadow_atlas->fbo;
vp_height=shadow_atlas->size;
uint32_t key = shadow_atlas->shadow_owners[p_light];
uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT)&0x3;
@ -4299,24 +4308,22 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa
render_list.sort_by_depth(false); //shadow is front to back for performance
glDepthMask(true);
glColorMask(0,0,0,0);
glColorMask(1,1,1,1);
glDisable(GL_BLEND);
glDisable(GL_DITHER);
glEnable(GL_DEPTH_TEST);
glBindFramebuffer(GL_FRAMEBUFFER,fbo);
if (custom_vp_size) {
glViewport(0,0,custom_vp_size,custom_vp_size);
glScissor(0,0,custom_vp_size,custom_vp_size);
} else {
glViewport(x,y,width,height);
glScissor(x,y,width,height);
}
//glViewport(x,vp_height-(height+y),width,height);
//glScissor(x,vp_height-(height+y),width,height);
glEnable(GL_SCISSOR_TEST);
glClearDepth(1.0);
glClear(GL_DEPTH_BUFFER_BIT);
@ -4331,7 +4338,7 @@ void RasterizerSceneGLES3::render_shadow(RID p_light,RID p_shadow_atlas,int p_pa
state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,true);
_render_list(render_list.elements,render_list.element_count,light_transform,light_projection,NULL,!flip_facing,false,true,false,false);
_render_list(render_list.elements,render_list.element_count,light_transform,light_projection,0,!flip_facing,false,true,false,false);
state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW,false);
state.scene_shader.set_conditional(SceneShaderGLES3::RENDER_SHADOW_DUAL_PARABOLOID,false);

View file

@ -531,6 +531,7 @@ public:
struct GIProbeInstance : public RID_Data {
RID data;
RasterizerStorageGLES3::GIProbe *probe;
GLuint tex_cache;
Vector3 cell_size_cache;
Vector3 bounds;
@ -542,7 +543,7 @@ public:
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_light_data(RID p_probe,RID p_base,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);

View file

@ -4695,6 +4695,8 @@ RID RasterizerStorageGLES3::gi_probe_create() {
gip->data_depth=0;
gip->bounds=AABB(Vector3(),Vector3(1,1,1));
gip->dynamic_range=1.0;
gip->energy=1.0;
gip->interior=false;
gip->version=1;
gip->cell_size=1.0;
@ -4773,7 +4775,7 @@ DVector<int> RasterizerStorageGLES3::gi_probe_get_dynamic_data(RID p_probe) cons
return gip->dynamic_data;
}
void RasterizerStorageGLES3::gi_probe_set_dynamic_range(RID p_probe,float p_range){
void RasterizerStorageGLES3::gi_probe_set_dynamic_range(RID p_probe,int p_range){
GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!gip);
@ -4781,7 +4783,7 @@ void RasterizerStorageGLES3::gi_probe_set_dynamic_range(RID p_probe,float p_rang
gip->dynamic_range=p_range;
}
float RasterizerStorageGLES3::gi_probe_get_dynamic_range(RID p_probe) const{
int 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);
@ -4789,6 +4791,41 @@ float RasterizerStorageGLES3::gi_probe_get_dynamic_range(RID p_probe) const{
return gip->dynamic_range;
}
void RasterizerStorageGLES3::gi_probe_set_energy(RID p_probe,float p_range){
GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!gip);
gip->energy=p_range;
}
void RasterizerStorageGLES3::gi_probe_set_interior(RID p_probe,bool p_enable) {
GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND(!gip);
gip->interior=p_enable;
}
bool RasterizerStorageGLES3::gi_probe_is_interior(RID p_probe) const{
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!gip,false);
return gip->interior;
}
float RasterizerStorageGLES3::gi_probe_get_energy(RID p_probe) const{
const GIProbe *gip = gi_probe_owner.getornull(p_probe);
ERR_FAIL_COND_V(!gip,0);
return gip->energy;
}
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) {

View file

@ -890,7 +890,9 @@ public:
Transform to_cell;
float cell_size;
float dynamic_range;
int dynamic_range;
float energy;
bool interior;
uint32_t version;
@ -921,9 +923,14 @@ public:
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_dynamic_range(RID p_probe,int p_range);
virtual int gi_probe_get_dynamic_range(RID p_probe) const;
virtual void gi_probe_set_energy(RID p_probe,float p_range);
virtual float gi_probe_get_energy(RID p_probe) const;
virtual void gi_probe_set_interior(RID p_probe,bool p_enable);
virtual bool gi_probe_is_interior(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;

View file

@ -845,14 +845,18 @@ 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 highp float gi_probe_multiplier1;
uniform bool gi_probe_blend_ambient1;
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 highp float gi_probe_multiplier2;
uniform bool gi_probe2_enabled;
uniform bool gi_probe_blend_ambient2;
vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance) {
vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 ambient, bool blend_ambient, 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;
@ -868,10 +872,12 @@ vec3 voxel_cone_trace(sampler3D probe, vec3 cell_size, vec3 pos, vec3 direction,
dist += diameter * 0.5;
}
color.rgb = mix(color.rgb,mix(ambient,color.rgb,alpha),blend_ambient);
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) {
void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_size,vec3 pos, vec3 ambient, vec3 environment, bool blend_ambient,float multiplier, mat3 normal_mtx,vec3 ref_vec, float roughness, out vec4 out_spec, out vec4 out_diff) {
@ -928,15 +934,19 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s
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,cone_angle_tan,max_distance);
light+=cone_weights[i] * voxel_cone_trace(probe,cell_size,probe_pos,ambient,blend_ambient,dir,cone_angle_tan,max_distance);
}
light*=multiplier;
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);
vec3 irr_light = voxel_cone_trace(probe,cell_size,probe_pos,environment,blend_ambient,ref_vec,tan(roughness * 0.5 * M_PI) ,max_distance);
irr_light *= multiplier;
//irr_light=vec3(0.0);
out_spec = vec4(irr_light*blend,blend);
@ -958,11 +968,18 @@ void gi_probes_compute(vec3 pos, vec3 normal, float roughness, vec3 specular, in
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);
vec3 ambient = out_ambient;
out_ambient = vec3(0.0);
vec3 environment = out_specular;
out_specular = vec3(0.0);
gi_probe_compute(gi_probe1,gi_probe_xform1,gi_probe_bounds1,gi_probe_cell_size1,pos,ambient,environment,gi_probe_blend_ambient1,gi_probe_multiplier1,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);
gi_probe_compute(gi_probe2,gi_probe_xform2,gi_probe_bounds2,gi_probe_cell_size2,pos,ambient,environment,gi_probe_blend_ambient2,gi_probe_multiplier2,normal_mat,ref_vec,roughness,spec_accum,diff_accum);
}
if (diff_accum.a>0.0) {

View file

@ -53,12 +53,35 @@ DVector<int> GIProbeData::get_dynamic_data() const{
return VS::get_singleton()->gi_probe_get_dynamic_data(probe);
}
void GIProbeData::set_dynamic_range(float p_range){
void GIProbeData::set_dynamic_range(int p_range){
VS::get_singleton()->gi_probe_set_dynamic_range(probe,p_range);
}
float GIProbeData::get_dynamic_range() const{
void GIProbeData::set_energy(float p_range) {
VS::get_singleton()->gi_probe_set_energy(probe,p_range);
}
float GIProbeData::get_energy() const{
return VS::get_singleton()->gi_probe_get_energy(probe);
}
void GIProbeData::set_interior(bool p_enable) {
VS::get_singleton()->gi_probe_set_interior(probe,p_enable);
}
bool GIProbeData::is_interior() const{
return VS::get_singleton()->gi_probe_is_interior(probe);
}
int GIProbeData::get_dynamic_range() const{
return VS::get_singleton()->gi_probe_get_dynamic_range(probe);
@ -154,15 +177,42 @@ Vector3 GIProbe::get_extents() const {
return extents;
}
void GIProbe::set_dynamic_range(float p_dynamic_range) {
void GIProbe::set_dynamic_range(int p_dynamic_range) {
dynamic_range=p_dynamic_range;
}
float GIProbe::get_dynamic_range() const {
int GIProbe::get_dynamic_range() const {
return dynamic_range;
}
void GIProbe::set_energy(float p_energy) {
energy=p_energy;
if (probe_data.is_valid()) {
probe_data->set_energy(energy);
}
}
float GIProbe::get_energy() const {
return energy;
}
void GIProbe::set_interior(bool p_enable) {
interior=p_enable;
if (probe_data.is_valid()) {
probe_data->set_interior(p_enable);
}
}
bool GIProbe::is_interior() const {
return interior;
}
#include "math.h"
#define FINDMINMAX(x0,x1,x2,min,max) \
@ -384,6 +434,8 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V
Color albedo_accum;
Color emission_accum;
Vector3 normal_accum;
float alpha=0.0;
//map to a grid average in the best axis for this face
@ -441,6 +493,9 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V
emission_accum.r+=p_material.emission[ofs].r;
emission_accum.g+=p_material.emission[ofs].g;
emission_accum.b+=p_material.emission[ofs].b;
normal_accum+=normal;
alpha+=1.0;
}
@ -471,6 +526,7 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V
emission_accum.g=p_material.emission[ofs].g*alpha;
emission_accum.b=p_material.emission[ofs].b*alpha;
normal_accum*=alpha;
} else {
@ -486,6 +542,9 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V
emission_accum.r*=accdiv;
emission_accum.g*=accdiv;
emission_accum.b*=accdiv;
normal_accum*=accdiv;
}
//put this temporarily here, corrected in a later step
@ -495,6 +554,9 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V
p_baker->bake_cells[p_idx].emission[0]+=emission_accum.r;
p_baker->bake_cells[p_idx].emission[1]+=emission_accum.g;
p_baker->bake_cells[p_idx].emission[2]+=emission_accum.b;
p_baker->bake_cells[p_idx].normal[0]+=normal_accum.x;
p_baker->bake_cells[p_idx].normal[1]+=normal_accum.y;
p_baker->bake_cells[p_idx].normal[2]+=normal_accum.z;
p_baker->bake_cells[p_idx].alpha+=alpha;
static const Vector3 side_normals[6]={
@ -506,11 +568,12 @@ void GIProbe::_plot_face(int p_idx, int p_level,int p_x,int p_y,int p_z, const V
Vector3( 0, 0, 1),
};
/*
for(int i=0;i<6;i++) {
if (normal.dot(side_normals[i])>CMP_EPSILON) {
p_baker->bake_cells[p_idx].used_sides|=(1<<i);
}
}
}*/
} else {
@ -589,8 +652,27 @@ void GIProbe::_fixup_plot(int p_idx, int p_level,int p_x,int p_y, int p_z,Baker
p_baker->bake_cells[p_idx].emission[1]/=alpha;
p_baker->bake_cells[p_idx].emission[2]/=alpha;
p_baker->bake_cells[p_idx].normal[0]/=alpha;
p_baker->bake_cells[p_idx].normal[1]/=alpha;
p_baker->bake_cells[p_idx].normal[2]/=alpha;
Vector3 n(p_baker->bake_cells[p_idx].normal[0],p_baker->bake_cells[p_idx].normal[1],p_baker->bake_cells[p_idx].normal[2]);
if (n.length()<0.01) {
//too much fight over normal, zero it
p_baker->bake_cells[p_idx].normal[0]=0;
p_baker->bake_cells[p_idx].normal[1]=0;
p_baker->bake_cells[p_idx].normal[2]=0;
} else {
n.normalize();
p_baker->bake_cells[p_idx].normal[0]=n.x;
p_baker->bake_cells[p_idx].normal[1]=n.y;
p_baker->bake_cells[p_idx].normal[2]=n.z;
}
p_baker->bake_cells[p_idx].alpha=1.0;
/*
//remove neighbours from used sides
for(int n=0;n<6;n++) {
@ -653,6 +735,7 @@ void GIProbe::_fixup_plot(int p_idx, int p_level,int p_x,int p_y, int p_z,Baker
p_baker->bake_cells[p_idx].used_sides&=~(1<<uint32_t(n));
}
}
*/
} else {
@ -687,6 +770,9 @@ void GIProbe::_fixup_plot(int p_idx, int p_level,int p_x,int p_y, int p_z,Baker
p_baker->bake_cells[p_idx].emission[0]=0;
p_baker->bake_cells[p_idx].emission[1]=0;
p_baker->bake_cells[p_idx].emission[2]=0;
p_baker->bake_cells[p_idx].normal[0]=0;
p_baker->bake_cells[p_idx].normal[1]=0;
p_baker->bake_cells[p_idx].normal[2]=0;
p_baker->bake_cells[p_idx].albedo[0]=0;
p_baker->bake_cells[p_idx].albedo[1]=0;
p_baker->bake_cells[p_idx].albedo[2]=0;
@ -1024,7 +1110,21 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug){
w32[ofs++]=em;
}
w32[ofs++]=baker.bake_cells[i].used_sides;
//w32[ofs++]=baker.bake_cells[i].used_sides;
{ //normal
Vector3 n(baker.bake_cells[i].normal[0],baker.bake_cells[i].normal[1],baker.bake_cells[i].normal[2]);
n=n*Vector3(0.5,0.5,0.5)+Vector3(0.5,0.5,0.5);
uint32_t norm=0;
norm|=uint32_t(CLAMP( n.x*255.0, 0, 255))<<16;
norm|=uint32_t(CLAMP( n.y*255.0, 0, 255))<<8;
norm|=uint32_t(CLAMP( n.z*255.0, 0, 255))<<0;
w32[ofs++]=norm;
}
w32[ofs++]=uint32_t(baker.bake_cells[i].alpha*65535.0);
}
@ -1036,6 +1136,9 @@ void GIProbe::bake(Node *p_from_node, bool p_create_visual_debug){
probe_data->set_bounds(AABB(-extents,extents*2.0));
probe_data->set_cell_size(baker.po2_bounds.size[longest_axis]/baker.axis_cell_size[longest_axis]);
probe_data->set_dynamic_data(data);
probe_data->set_dynamic_range(dynamic_range);
probe_data->set_energy(energy);
probe_data->set_interior(interior);
probe_data->set_to_cell_xform(baker.to_cell_space);
set_probe_data(probe_data);
@ -1212,13 +1315,21 @@ void GIProbe::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_dynamic_range","max"),&GIProbe::set_dynamic_range);
ObjectTypeDB::bind_method(_MD("get_dynamic_range"),&GIProbe::get_dynamic_range);
ObjectTypeDB::bind_method(_MD("set_energy","max"),&GIProbe::set_energy);
ObjectTypeDB::bind_method(_MD("get_energy"),&GIProbe::get_energy);
ObjectTypeDB::bind_method(_MD("set_interior","enable"),&GIProbe::set_interior);
ObjectTypeDB::bind_method(_MD("is_interior"),&GIProbe::is_interior);
ObjectTypeDB::bind_method(_MD("bake","from_node","create_visual_debug"),&GIProbe::bake,DEFVAL(Variant()),DEFVAL(false));
ObjectTypeDB::bind_method(_MD("debug_bake"),&GIProbe::_debug_bake);
ObjectTypeDB::set_method_flags(get_type_static(),_SCS("debug_bake"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR);
ADD_PROPERTY( PropertyInfo(Variant::INT,"subdiv",PROPERTY_HINT_ENUM,"64,128,256,512"),_SCS("set_subdiv"),_SCS("get_subdiv"));
ADD_PROPERTY( PropertyInfo(Variant::VECTOR3,"extents"),_SCS("set_extents"),_SCS("get_extents"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"dynamic_range",PROPERTY_HINT_RANGE,"0,8,0.01"),_SCS("set_dynamic_range"),_SCS("get_dynamic_range"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"dynamic_range",PROPERTY_HINT_RANGE,"1,16,1"),_SCS("set_dynamic_range"),_SCS("get_dynamic_range"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"energy",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_energy"),_SCS("get_energy"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"interior"),_SCS("set_interior"),_SCS("is_interior"));
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"data",PROPERTY_HINT_RESOURCE_TYPE,"GIProbeData"),_SCS("set_probe_data"),_SCS("get_probe_data"));
@ -1232,10 +1343,12 @@ void GIProbe::_bind_methods() {
GIProbe::GIProbe() {
subdiv=SUBDIV_128;
dynamic_range=1.0;
dynamic_range=4;
energy=1.0;
extents=Vector3(10,10,10);
color_scan_cell_width=4;
bake_texture_size=128;
interior=false;
gi_probe = VS::get_singleton()->gi_probe_create();

View file

@ -31,8 +31,14 @@ public:
void set_dynamic_data(const DVector<int>& p_data);
DVector<int> get_dynamic_data() const;
void set_dynamic_range(float p_range);
float get_dynamic_range() const;
void set_dynamic_range(int p_range);
int get_dynamic_range() const;
void set_energy(float p_range);
float get_energy() const;
void set_interior(bool p_enable);
bool is_interior() const;
void set_static_data(const DVector<uint8_t>& p_data,DataFormat p_format,int p_width,int p_height,int p_depth);
DVector<uint8_t> get_static_data() const;
@ -73,6 +79,7 @@ private:
uint32_t childs[8];
float albedo[3]; //albedo in RGB24
float emission[3]; //accumulated light in 16:16 fixed point (needs to be integer for moving lights fast)
float normal[3];
uint32_t used_sides;
float alpha; //used for upsampling
@ -84,6 +91,7 @@ private:
for(int i=0;i<3;i++) {
emission[i]=0;
albedo[i]=0;
normal[i]=0;
}
alpha=0;
used_sides=0;
@ -126,7 +134,9 @@ private:
Subdiv subdiv;
Vector3 extents;
float dynamic_range;
int dynamic_range;
float energy;
bool interior;
int color_scan_cell_width;
int bake_texture_size;
@ -157,8 +167,15 @@ public:
void set_extents(const Vector3& p_extents);
Vector3 get_extents() const;
void set_dynamic_range(float p_dynamic_range);
float get_dynamic_range() const;
void set_dynamic_range(int p_dynamic_range);
int get_dynamic_range() const;
void set_energy(float p_energy);
float get_energy() const;
void set_interior(bool p_enable);
bool is_interior() const;
void bake(Node *p_from_node=NULL,bool p_create_visual_debug=false);

View file

@ -1283,6 +1283,9 @@ bool Viewport::get_clear_on_new_frame() const{
void Viewport::set_shadow_atlas_size(int p_size) {
if (shadow_atlas_size==p_size)
return;
shadow_atlas_size=p_size;
VS::get_singleton()->viewport_set_shadow_atlas_size(viewport,p_size);
}

View file

@ -149,7 +149,7 @@ public:
virtual bool reflection_probe_instance_postprocess_step(RID p_instance)=0;
virtual RID gi_probe_instance_create()=0;
virtual void gi_probe_instance_set_light_data(RID p_probe,RID p_data)=0;
virtual void gi_probe_instance_set_light_data(RID p_probe,RID p_base,RID p_data)=0;
virtual void gi_probe_instance_set_transform_to_data(RID p_probe,const Transform& p_xform)=0;
virtual void gi_probe_instance_set_bounds(RID p_probe,const Vector3& p_bounds)=0;
@ -418,9 +418,14 @@ public:
virtual void gi_probe_set_dynamic_data(RID p_probe,const DVector<int>& p_data)=0;
virtual DVector<int> gi_probe_get_dynamic_data(RID p_probe) const=0;
virtual void gi_probe_set_dynamic_range(RID p_probe,float p_range)=0;
virtual float gi_probe_get_dynamic_range(RID p_probe) const=0;
virtual void gi_probe_set_dynamic_range(RID p_probe,int p_range)=0;
virtual int gi_probe_get_dynamic_range(RID p_probe) const=0;
virtual void gi_probe_set_energy(RID p_probe,float p_range)=0;
virtual float gi_probe_get_energy(RID p_probe) const=0;
virtual void gi_probe_set_interior(RID p_probe,bool p_enable)=0;
virtual bool gi_probe_is_interior(RID p_probe) const=0;
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)=0;
virtual DVector<uint8_t> gi_probe_get_static_data(RID p_gi_probe) const=0;

View file

@ -816,8 +816,14 @@ public:
BIND2(gi_probe_set_to_cell_xform,RID,const Transform&)
BIND1RC(Transform,gi_probe_get_to_cell_xform,RID)
BIND2(gi_probe_set_dynamic_range,RID,float)
BIND1RC(float,gi_probe_get_dynamic_range,RID)
BIND2(gi_probe_set_dynamic_range,RID,int)
BIND1RC(int,gi_probe_get_dynamic_range,RID)
BIND2(gi_probe_set_energy,RID,float)
BIND1RC(float,gi_probe_get_energy,RID)
BIND2(gi_probe_set_interior,RID,bool)
BIND1RC(bool,gi_probe_is_interior,RID)
BIND2(gi_probe_set_dynamic_data,RID,const DVector<int>& )
BIND1RC( DVector<int>,gi_probe_get_dynamic_data,RID)

View file

@ -1641,6 +1641,7 @@ void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,const
}
}
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);
}
@ -2203,10 +2204,10 @@ void VisualServerScene::_render_scene(const Transform p_cam_transform,const Came
}
bool redraw = VSG::scene_render->shadow_atlas_update_light(p_shadow_atlas,light->instance,coverage,light->last_version);
if (redraw) {
print_line("redraw shadow");
//must redraw!
_light_instance_update_shadow(ins,p_cam_transform,p_cam_projection,p_cam_orthogonal,p_shadow_atlas,scenario);
}
@ -2407,6 +2408,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) {
probe->dynamic.probe_data=VSG::storage->gi_probe_dynamic_data_create(header->width,header->height,header->depth);
probe->dynamic.bake_dynamic_range=VSG::storage->gi_probe_get_dynamic_range(p_instance->base);
probe->dynamic.mipmaps_3d.clear();
@ -2443,7 +2445,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) {
probe->dynamic.light_to_cell_xform=cell_to_xform * p_instance->transform.affine_inverse();
VSG::scene_render->gi_probe_instance_set_light_data(probe->probe_instance,probe->dynamic.probe_data);
VSG::scene_render->gi_probe_instance_set_light_data(probe->probe_instance,p_instance->base,probe->dynamic.probe_data);
VSG::scene_render->gi_probe_instance_set_transform_to_data(probe->probe_instance,probe->dynamic.light_to_cell_xform);
@ -2457,7 +2459,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) {
probe->dynamic.enabled=false;
probe->invalid=!data.is_valid();
if (data.is_valid()) {
VSG::scene_render->gi_probe_instance_set_light_data(probe->probe_instance,data);
VSG::scene_render->gi_probe_instance_set_light_data(probe->probe_instance,p_instance->base,data);
}
}
@ -2541,6 +2543,30 @@ uint32_t VisualServerScene::_gi_bake_find_cell(const GIProbeDataCell *cells,int
}
static float _get_normal_advance(const Vector3& p_normal ) {
Vector3 normal = p_normal;
Vector3 unorm = normal.abs();
if ( (unorm.x >= unorm.y) && (unorm.x >= unorm.z) ) {
// x code
unorm = normal.x > 0.0 ? Vector3( 1.0, 0.0, 0.0 ) : Vector3( -1.0, 0.0, 0.0 ) ;
} else if ( (unorm.y > unorm.x) && (unorm.y >= unorm.z) ) {
// y code
unorm = normal.y > 0.0 ? Vector3( 0.0, 1.0, 0.0 ) : Vector3( 0.0, -1.0, 0.0 ) ;
} else if ( (unorm.z > unorm.x) && (unorm.z > unorm.y) ) {
// z code
unorm = normal.z > 0.0 ? Vector3( 0.0, 0.0, 1.0 ) : Vector3( 0.0, 0.0, -1.0 ) ;
} else {
// oh-no we messed up code
// has to be
unorm = Vector3( 1.0, 0.0, 0.0 );
}
return 1.0/normal.dot(unorm);
}
void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header,const GIProbeDataCell *cells,InstanceGIProbeData::LocalData *local_data,const uint32_t *leaves,int leaf_count, const InstanceGIProbeData::LightCache& light_cache,int sign) {
@ -2548,20 +2574,20 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header,con
int light_g = int(light_cache.color.g * light_cache.energy * 1024.0)*sign;
int light_b = int(light_cache.color.b * light_cache.energy * 1024.0)*sign;
float limits[3]={float(header->width),float(header->height),float(header->depth)};
Plane clip[3];
int clip_planes=0;
switch(light_cache.type) {
case VS::LIGHT_DIRECTIONAL: {
float limits[3]={float(header->width),float(header->height),float(header->depth)};
Plane clip[3];
int clip_planes=0;
float max_len = Vector3(limits[0],limits[1],limits[2]).length()*1.1;
Vector3 light_axis = -light_cache.transform.basis.get_axis(2).normalized();
print_line("transform directional, axis: "+light_axis);
print_line("limits: "+Vector3(limits[0],limits[1],limits[2]));
for(int i=0;i<3;i++) {
if (ABS(light_axis[i])<CMP_EPSILON)
@ -2578,29 +2604,7 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header,con
clip_planes++;
}
float distance_adv;
{
Vector3 normal = light_axis;
Vector3 unorm = normal.abs();
if ( (unorm.x >= unorm.y) && (unorm.x >= unorm.z) ) {
// x code
unorm = normal.x > 0.0 ? Vector3( 1.0, 0.0, 0.0 ) : Vector3( -1.0, 0.0, 0.0 ) ;
} else if ( (unorm.y > unorm.x) && (unorm.y >= unorm.z) ) {
// y code
unorm = normal.y > 0.0 ? Vector3( 0.0, 1.0, 0.0 ) : Vector3( 0.0, -1.0, 0.0 ) ;
} else if ( (unorm.z > unorm.x) && (unorm.z > unorm.y) ) {
// z code
unorm = normal.z > 0.0 ? Vector3( 0.0, 0.0, 1.0 ) : Vector3( 0.0, 0.0, -1.0 ) ;
} else {
// oh-no we messed up code
// has to be
unorm = Vector3( 1.0, 0.0, 0.0 );
}
distance_adv = 1.0/normal.dot(unorm);
}
float distance_adv = _get_normal_advance(light_axis);
int success_count=0;
@ -2614,8 +2618,19 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header,con
InstanceGIProbeData::LocalData *light = &local_data[idx];
Vector3 to(light->pos[0]+0.5,light->pos[1]+0.5,light->pos[2]+0.5);
Vector3 norm (
(((cells[idx].normal>>16)&0xFF)/255.0)*2.0-1.0,
(((cells[idx].normal>>8)&0xFF)/255.0)*2.0-1.0,
(((cells[idx].normal>>0)&0xFF)/255.0)*2.0-1.0
);
float att = norm.dot(-light_axis);
if (att<0.001) {
//not lighting towards this
continue;
}
Vector3 from = to - max_len * light_axis;
for(int j=0;j<clip_planes;j++) {
@ -2642,16 +2657,130 @@ void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header,con
if (result==idx) {
//cell hit itself! hooray!
light->energy[0]+=(uint32_t(light_r)*((cell->albedo>>16)&0xFF))>>8;
light->energy[1]+=(uint32_t(light_g)*((cell->albedo>>8)&0xFF))>>8;
light->energy[2]+=(uint32_t(light_b)*((cell->albedo)&0xFF))>>8;
success_count++;
light->energy[0]+=int32_t(light_r*att*((cell->albedo>>16)&0xFF)/255.0);
light->energy[1]+=int32_t(light_g*att*((cell->albedo>>8)&0xFF)/255.0);
light->energy[2]+=int32_t(light_b*att*((cell->albedo)&0xFF)/255.0);
success_count++;
}
}
print_line("BAKE TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0));
print_line("valid cells: "+itos(success_count));
} break;
case VS::LIGHT_OMNI:
case VS::LIGHT_SPOT: {
uint64_t us = OS::get_singleton()->get_ticks_usec();
Vector3 light_pos = light_cache.transform.origin;
Vector3 spot_axis = -light_cache.transform.basis.get_axis(2).normalized();
float local_radius = light_cache.radius * light_cache.transform.basis.get_axis(2).length();
for(int i=0;i<leaf_count;i++) {
uint32_t idx = leaves[i];
const GIProbeDataCell *cell = &cells[idx];
InstanceGIProbeData::LocalData *light = &local_data[idx];
Vector3 to(light->pos[0]+0.5,light->pos[1]+0.5,light->pos[2]+0.5);
Vector3 norm (
(((cells[idx].normal>>16)&0xFF)/255.0)*2.0-1.0,
(((cells[idx].normal>>8)&0xFF)/255.0)*2.0-1.0,
(((cells[idx].normal>>0)&0xFF)/255.0)*2.0-1.0
);
Vector3 light_axis = (to - light_pos).normalized();
float distance_adv = _get_normal_advance(light_axis);
float att = norm.dot(-light_axis);
if (att<0.001) {
//not lighting towards this
continue;
}
{
float d = light_pos.distance_to(to);
if (d+distance_adv > local_radius)
continue; // too far away
float dt = CLAMP((d+distance_adv)/local_radius,0,1);
att*= pow(1.0-dt,light_cache.attenuation);
}
if (light_cache.type==VS::LIGHT_SPOT) {
float angle = Math::rad2deg(acos(light_axis.dot(spot_axis)));
if (angle > light_cache.spot_angle)
continue;
float d = CLAMP(angle/light_cache.spot_angle,1,0);
att*= pow(1.0-d,light_cache.spot_attenuation);
}
clip_planes=0;
for(int c=0;c<3;c++) {
if (ABS(light_axis[c])<CMP_EPSILON)
continue;
clip[clip_planes].normal[c]=1.0;
if (light_axis[c]<0) {
clip[clip_planes].d=limits[c]+1;
} else {
clip[clip_planes].d-=1.0;
}
clip_planes++;
}
Vector3 from = light_pos;
for(int j=0;j<clip_planes;j++) {
clip[j].intersects_segment(from,to,&from);
}
float distance = (to - from).length();
distance-=Math::fmod(distance,distance_adv); //make it reach the center of the box always, but this tame make it closer
from = to - light_axis * distance;
uint32_t result=0xFFFFFFFF;
while(distance>-distance_adv) { //use this to avoid precision errors
result = _gi_bake_find_cell(cells,int(floor(from.x)),int(floor(from.y)),int(floor(from.z)),header->cell_subdiv);
if (result!=0xFFFFFFFF) {
break;
}
from+=light_axis*distance_adv;
distance-=distance_adv;
}
if (result==idx) {
//cell hit itself! hooray!
light->energy[0]+=int32_t(light_r*att*((cell->albedo>>16)&0xFF)/255.0);
light->energy[1]+=int32_t(light_g*att*((cell->albedo>>8)&0xFF)/255.0);
light->energy[2]+=int32_t(light_b*att*((cell->albedo)&0xFF)/255.0);
}
}
print_line("BAKE TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0));
} break;
}
}
@ -2760,9 +2889,9 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) {
uint32_t idx = level_cells[j];
uint32_t r = local_data[idx].energy[0]>>2;
uint32_t g = local_data[idx].energy[1]>>2;
uint32_t b = local_data[idx].energy[2]>>2;
uint32_t r = (uint32_t(local_data[idx].energy[0])/probe_data->dynamic.bake_dynamic_range)>>2;
uint32_t g = (uint32_t(local_data[idx].energy[1])/probe_data->dynamic.bake_dynamic_range)>>2;
uint32_t b = (uint32_t(local_data[idx].energy[2])/probe_data->dynamic.bake_dynamic_range)>>2;
uint32_t a = cells[idx].alpha>>8;
uint32_t mm_ofs = sizes[0]*sizes[1]*(local_data[idx].pos[2]) + sizes[0]*(local_data[idx].pos[1]) + (local_data[idx].pos[0]);

View file

@ -432,6 +432,7 @@ public:
Vector<Vector<uint32_t> > level_cell_lists;
RID probe_data;
bool enabled;
int bake_dynamic_range;
Vector< DVector<uint8_t> > mipmaps_3d;
@ -536,7 +537,7 @@ public:
uint32_t children[8];
uint32_t albedo;
uint32_t emission;
uint32_t sides_used;
uint32_t normal;
uint32_t alpha;
};
@ -560,7 +561,6 @@ public:
_FORCE_INLINE_ uint32_t _gi_bake_find_cell(const GIProbeDataCell *cells,int x,int y, int z,int p_cell_subdiv);
void _bake_gi_downscale_light(int p_idx, int p_level, const GIProbeDataCell* p_cells, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data);
void _bake_gi_probe_light(const GIProbeDataHeader *header,const GIProbeDataCell *cells,InstanceGIProbeData::LocalData *local_data,const uint32_t *leaves,int p_leaf_count, const InstanceGIProbeData::LightCache& light_cache,int p_sign);
void _bake_gi_probe(Instance *p_probe);
bool _check_gi_probe(Instance *p_gi_probe);

View file

@ -461,8 +461,14 @@ public:
virtual void gi_probe_set_dynamic_data(RID p_probe,const DVector<int>& p_data)=0;
virtual DVector<int> gi_probe_get_dynamic_data(RID p_probe) const=0;
virtual void gi_probe_set_dynamic_range(RID p_probe,float p_range)=0;
virtual float gi_probe_get_dynamic_range(RID p_probe) const=0;
virtual void gi_probe_set_dynamic_range(RID p_probe,int p_range)=0;
virtual int gi_probe_get_dynamic_range(RID p_probe) const=0;
virtual void gi_probe_set_energy(RID p_probe,float p_range)=0;
virtual float gi_probe_get_energy(RID p_probe) const=0;
virtual void gi_probe_set_interior(RID p_probe,bool p_enable)=0;
virtual bool gi_probe_is_interior(RID p_probe) const=0;
enum GIProbeDataFormat {
GI_PROBE_DATA_RGBA8,