mirror of
https://github.com/godotengine/godot.git
synced 2026-01-06 10:11:57 +03:00
begin work on new particle system
This commit is contained in:
@@ -4882,37 +4882,45 @@ uint32_t RasterizerStorageGLES3::gi_probe_get_version(RID p_probe) {
|
||||
return gip->version;
|
||||
}
|
||||
|
||||
RID RasterizerStorageGLES3::gi_probe_dynamic_data_create(int p_width,int p_height,int p_depth) {
|
||||
RasterizerStorage::GIProbeCompression RasterizerStorageGLES3::gi_probe_get_dynamic_data_get_preferred_compression() const {
|
||||
if (config.s3tc_supported) {
|
||||
return GI_PROBE_S3TC;
|
||||
} else {
|
||||
return GI_PROBE_UNCOMPRESSED;
|
||||
}
|
||||
}
|
||||
|
||||
RID RasterizerStorageGLES3::gi_probe_dynamic_data_create(int p_width, int p_height, int p_depth, GIProbeCompression p_compression) {
|
||||
|
||||
GIProbeData *gipd = memnew( GIProbeData );
|
||||
|
||||
gipd->width=p_width;
|
||||
gipd->height=p_height;
|
||||
gipd->depth=p_depth;
|
||||
gipd->compression=p_compression;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glGenTextures(1,&gipd->tex_id);
|
||||
glBindTexture(GL_TEXTURE_3D,gipd->tex_id);
|
||||
|
||||
int level=0;
|
||||
int min_size=1;
|
||||
|
||||
if (gipd->compression==GI_PROBE_S3TC) {
|
||||
min_size=4;
|
||||
}
|
||||
|
||||
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;
|
||||
if (gipd->compression==GI_PROBE_S3TC) {
|
||||
int size = p_width * p_height * p_depth;
|
||||
glCompressedTexImage3D(GL_TEXTURE_3D,level,_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT,p_width,p_height,p_depth,0, size,NULL);
|
||||
} else {
|
||||
glTexImage3D(GL_TEXTURE_3D,level,GL_RGBA8,p_width,p_height,p_depth,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
|
||||
}
|
||||
|
||||
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)
|
||||
if (p_width<=min_size || p_height<=min_size || p_depth<=min_size)
|
||||
break;
|
||||
p_width>>=1;
|
||||
p_height>>=1;
|
||||
@@ -4933,7 +4941,7 @@ RID RasterizerStorageGLES3::gi_probe_dynamic_data_create(int p_width,int p_heigh
|
||||
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) {
|
||||
void RasterizerStorageGLES3::gi_probe_dynamic_data_update(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);
|
||||
@@ -4957,14 +4965,168 @@ void RasterizerStorageGLES3::gi_probe_dynamic_data_update_rgba8(RID p_gi_probe_d
|
||||
*/
|
||||
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);
|
||||
if (gipd->compression==GI_PROBE_S3TC) {
|
||||
int size = (gipd->width>>p_mipmap) * (gipd->height>>p_mipmap) * p_slice_count;
|
||||
glCompressedTexSubImage3D(GL_TEXTURE_3D,p_mipmap,0,0,p_depth_slice,gipd->width>>p_mipmap,gipd->height>>p_mipmap,p_slice_count,_EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT,size, p_data);
|
||||
} else {
|
||||
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));
|
||||
|
||||
}
|
||||
|
||||
///////
|
||||
|
||||
|
||||
RID RasterizerStorageGLES3::particles_create() {
|
||||
|
||||
Particles *particles = memnew( Particles );
|
||||
|
||||
|
||||
return particles_owner.make_rid(particles);
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::particles_set_emitting(RID p_particles,bool p_emitting) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
particles->emitting=p_emitting;
|
||||
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_amount(RID p_particles,int p_amount) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_lifetime(RID p_particles,float p_lifetime){
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
particles->lifetime=p_lifetime;
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_pre_process_time(RID p_particles,float p_time) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
particles->pre_process_time=p_time;
|
||||
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_explosiveness_ratio(RID p_particles,float p_ratio) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
particles->explosiveness=p_ratio;
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_randomness_ratio(RID p_particles,float p_ratio) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
particles->randomness=p_ratio;
|
||||
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_custom_aabb(RID p_particles,const AABB& p_aabb) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
particles->custom_aabb=p_aabb;
|
||||
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_gravity(RID p_particles,const Vector3& p_gravity) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
|
||||
particles->gravity=p_gravity;
|
||||
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_use_local_coordinates(RID p_particles,bool p_enable) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
|
||||
particles->use_local_coords=p_enable;
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_process_material(RID p_particles,RID p_material) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
|
||||
particles->process_material=p_material;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::particles_set_emission_shape(RID p_particles, VS::ParticlesEmissionShape p_shape) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
|
||||
particles->emission_shape=p_shape;
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_emission_sphere_radius(RID p_particles,float p_radius) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
|
||||
particles->emission_sphere_radius=p_radius;
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_emission_box_extents(RID p_particles,const Vector3& p_extents) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
|
||||
particles->emission_box_extents=p_extents;
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_emission_points(RID p_particles,const DVector<Vector3>& p_points) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
|
||||
particles->emission_points=p_points;
|
||||
}
|
||||
|
||||
|
||||
void RasterizerStorageGLES3::particles_set_draw_order(RID p_particles,VS::ParticlesDrawOrder p_order) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
|
||||
particles->draw_order=p_order;
|
||||
}
|
||||
|
||||
void RasterizerStorageGLES3::particles_set_draw_passes(RID p_particles,int p_count) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
|
||||
particles->draw_passes.resize(p_count);
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_draw_pass_material(RID p_particles,int p_pass, RID p_material) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
ERR_FAIL_INDEX(p_pass,particles->draw_passes.size());
|
||||
p_pass,particles->draw_passes[p_pass].material=p_material;
|
||||
|
||||
}
|
||||
void RasterizerStorageGLES3::particles_set_draw_pass_mesh(RID p_particles,int p_pass, RID p_mesh) {
|
||||
|
||||
Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND(!particles);
|
||||
ERR_FAIL_INDEX(p_pass,particles->draw_passes.size());
|
||||
p_pass,particles->draw_passes[p_pass].mesh=p_mesh;
|
||||
|
||||
}
|
||||
|
||||
AABB RasterizerStorageGLES3::particles_get_current_aabb(RID p_particles) {
|
||||
|
||||
const Particles *particles = particles_owner.getornull(p_particles);
|
||||
ERR_FAIL_COND_V(!particles,AABB());
|
||||
|
||||
return particles->computed_aabb;
|
||||
}
|
||||
|
||||
////////
|
||||
|
||||
void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance) {
|
||||
|
||||
|
||||
@@ -941,6 +941,7 @@ public:
|
||||
int depth;
|
||||
int levels;
|
||||
GLuint tex_id;
|
||||
GIProbeCompression compression;
|
||||
|
||||
GIProbeData() {
|
||||
}
|
||||
@@ -948,9 +949,90 @@ public:
|
||||
|
||||
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 GIProbeCompression gi_probe_get_dynamic_data_get_preferred_compression() const;
|
||||
virtual RID gi_probe_dynamic_data_create(int p_width,int p_height,int p_depth,GIProbeCompression p_compression);
|
||||
virtual void gi_probe_dynamic_data_update(RID p_gi_probe_data,int p_depth_slice,int p_slice_count,int p_mipmap,const void* p_data);
|
||||
|
||||
/* PARTICLES */
|
||||
|
||||
struct Particles : public Instantiable {
|
||||
|
||||
bool emitting;
|
||||
int amount;
|
||||
float lifetime;
|
||||
float pre_process_time;
|
||||
float explosiveness;
|
||||
float randomness;
|
||||
AABB custom_aabb;
|
||||
Vector3 gravity;
|
||||
bool use_local_coords;
|
||||
RID process_material;
|
||||
|
||||
VS::ParticlesEmissionShape emission_shape;
|
||||
float emission_sphere_radius;
|
||||
Vector3 emission_box_extents;
|
||||
DVector<Vector3> emission_points;
|
||||
GLuint emission_point_texture;
|
||||
|
||||
VS::ParticlesDrawOrder draw_order;
|
||||
struct DrawPass {
|
||||
RID mesh;
|
||||
RID material;
|
||||
};
|
||||
|
||||
Vector<DrawPass> draw_passes;
|
||||
|
||||
AABB computed_aabb;
|
||||
|
||||
Particles() {
|
||||
emitting=false;
|
||||
amount=0;
|
||||
lifetime=1.0;;
|
||||
pre_process_time=0.0;
|
||||
explosiveness=0.0;
|
||||
randomness=0.0;
|
||||
use_local_coords=true;
|
||||
|
||||
draw_order=VS::PARTICLES_DRAW_ORDER_INDEX;
|
||||
emission_shape=VS::PARTICLES_EMSSION_POINT;
|
||||
emission_sphere_radius=1.0;
|
||||
float emission_sphere_radius;
|
||||
emission_box_extents=Vector3(1,1,1);
|
||||
emission_point_texture=0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
mutable RID_Owner<Particles> particles_owner;
|
||||
|
||||
virtual RID particles_create();
|
||||
|
||||
virtual void particles_set_emitting(RID p_particles,bool p_emitting);
|
||||
virtual void particles_set_amount(RID p_particles,int p_amount);
|
||||
virtual void particles_set_lifetime(RID p_particles,float p_lifetime);
|
||||
virtual void particles_set_pre_process_time(RID p_particles,float p_time);
|
||||
virtual void particles_set_explosiveness_ratio(RID p_particles,float p_ratio);
|
||||
virtual void particles_set_randomness_ratio(RID p_particles,float p_ratio);
|
||||
virtual void particles_set_custom_aabb(RID p_particles,const AABB& p_aabb);
|
||||
virtual void particles_set_gravity(RID p_particles,const Vector3& p_gravity);
|
||||
virtual void particles_set_use_local_coordinates(RID p_particles,bool p_enable);
|
||||
virtual void particles_set_process_material(RID p_particles,RID p_material);
|
||||
|
||||
virtual void particles_set_emission_shape(RID p_particles,VS::ParticlesEmissionShape p_shape);
|
||||
virtual void particles_set_emission_sphere_radius(RID p_particles,float p_radius);
|
||||
virtual void particles_set_emission_box_extents(RID p_particles,const Vector3& p_extents);
|
||||
virtual void particles_set_emission_points(RID p_particles,const DVector<Vector3>& p_points);
|
||||
|
||||
|
||||
virtual void particles_set_draw_order(RID p_particles,VS::ParticlesDrawOrder p_order);
|
||||
|
||||
virtual void particles_set_draw_passes(RID p_particles,int p_count);
|
||||
virtual void particles_set_draw_pass_material(RID p_particles,int p_pass, RID p_material);
|
||||
virtual void particles_set_draw_pass_mesh(RID p_particles,int p_pass, RID p_mesh);
|
||||
|
||||
virtual AABB particles_get_current_aabb(RID p_particles);
|
||||
|
||||
/* INSTANCE */
|
||||
|
||||
virtual void instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance);
|
||||
virtual void instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance);
|
||||
|
||||
@@ -17,5 +17,6 @@ if env['BUILDERS'].has_key('GLES3_GLSL'):
|
||||
env.GLES3_GLSL('ssao_blur.glsl');
|
||||
env.GLES3_GLSL('exposure.glsl');
|
||||
env.GLES3_GLSL('tonemap.glsl');
|
||||
env.GLES3_GLSL('particles.glsl');
|
||||
|
||||
|
||||
|
||||
114
drivers/gles3/shaders/particles.glsl
Normal file
114
drivers/gles3/shaders/particles.glsl
Normal file
@@ -0,0 +1,114 @@
|
||||
[vertex]
|
||||
|
||||
|
||||
|
||||
layout(location=0) in highp vec4 pos_lifetime;
|
||||
layout(location=1) in highp vec4 color;
|
||||
layout(location=2) in highp vec4 velocity_seed;
|
||||
layout(location=3) in highp vec4 rot_active;
|
||||
|
||||
|
||||
struct Attractor {
|
||||
|
||||
vec3 pos;
|
||||
vec3 dir;
|
||||
float radius;
|
||||
float eat_radius;
|
||||
float strength;
|
||||
float attenuation;
|
||||
};
|
||||
|
||||
#define MAX_ATTRACTORS 64
|
||||
|
||||
uniform mat4 origin;
|
||||
uniform float system_phase;
|
||||
uniform float prev_system_phase;
|
||||
uniform float total_particles;
|
||||
uniform float explosiveness;
|
||||
uniform vec4 time;
|
||||
uniform float delta;
|
||||
uniform vec3 gravity;
|
||||
uniform int attractor_count;
|
||||
uniform Attractor attractors[MAX_ATTRACTORS];
|
||||
|
||||
|
||||
out highp vec4 out_pos_lifetime; //tfb:
|
||||
out highp vec4 out_color; //tfb:
|
||||
out highp vec4 out_velocity_seed; //tfb:
|
||||
out highp vec4 out_rot_active; //tfb:
|
||||
|
||||
void main() {
|
||||
|
||||
bool apply_forces=true;
|
||||
bool apply_velocity=true;
|
||||
|
||||
float mass = 1.0;
|
||||
|
||||
float restart_phase = float(gl_InstanceID)/total_particles;
|
||||
restart_phase*= explosiveness;
|
||||
bool restart=false;
|
||||
|
||||
if (system_phase > prev_system_phase) {
|
||||
restart = prev_system_phase < restart_phase && system_phase >= restart_phase;
|
||||
} else {
|
||||
restart = prev_system_phase < restart_phase || system_phase >= restart_phase;
|
||||
}
|
||||
|
||||
if (restart) {
|
||||
out_rot_active.a=1.0;
|
||||
}
|
||||
|
||||
out_pos_lifetime=pos_lifetime;
|
||||
out_color=color;
|
||||
out_velocity_seed=velocity_seed;
|
||||
out_rot_active=rot_active;
|
||||
|
||||
if (out_rot_active.a) {
|
||||
//execute shader
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (apply_forces) {
|
||||
|
||||
vec3 force = gravity;
|
||||
for(int i=0;i<attractor_count;i++) {
|
||||
|
||||
vec3 rel_vec = out_pos_lifetime.xyz - attractors[i].pos;
|
||||
float dist = rel_vec.length();
|
||||
if (attractors[i].radius < dist)
|
||||
continue;
|
||||
if (attractors[i].eat_radius>0 && attractors[i].eat_radius > dist) {
|
||||
rot_active.a=0.0;
|
||||
}
|
||||
|
||||
rel_vec = normalize(rel_vec);
|
||||
|
||||
float attenuation = pow(dist / attractors[i].radius,attractors[i].attenuation);
|
||||
|
||||
if (attractors[i].dir==vec3(0.0)) {
|
||||
//towards center
|
||||
force+=attractors[i].strength * rel_vec * attenuation * mass;
|
||||
} else {
|
||||
force+=attractors[i].strength * attractors[i].dir * attenuation *mass;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
out_velocity_seed.xyz += force * delta;
|
||||
}
|
||||
|
||||
if (apply_velocity) {
|
||||
|
||||
out_pos_lifetime.xyz += out_velocity_seed.xyz * delta;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[fragment]
|
||||
|
||||
|
||||
void main() {
|
||||
|
||||
|
||||
}
|
||||
@@ -899,8 +899,10 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s
|
||||
float blend = 1.001-max(blendv.x,max(blendv.y,blendv.z));
|
||||
blend=1.0;
|
||||
|
||||
float max_distance = length(bounds);
|
||||
|
||||
//radiance
|
||||
#ifdef VCT_QUALITY_HIGH
|
||||
#ifndef VCT_QUALITY_HIGH
|
||||
|
||||
#define MAX_CONE_DIRS 6
|
||||
vec3 cone_dirs[MAX_CONE_DIRS] = vec3[] (
|
||||
@@ -914,6 +916,7 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s
|
||||
|
||||
float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15);
|
||||
float cone_angle_tan = 0.577;
|
||||
float min_ref_tan = 0.0;
|
||||
#else
|
||||
|
||||
#define MAX_CONE_DIRS 4
|
||||
@@ -927,9 +930,10 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s
|
||||
|
||||
float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.25, 0.25, 0.25);
|
||||
float cone_angle_tan = 0.98269;
|
||||
max_distance*=0.5;
|
||||
float min_ref_tan = 0.2;
|
||||
|
||||
#endif
|
||||
float max_distance = length(bounds);
|
||||
vec3 light=vec3(0.0);
|
||||
for(int i=0;i<MAX_CONE_DIRS;i++) {
|
||||
|
||||
@@ -944,7 +948,7 @@ void gi_probe_compute(sampler3D probe, mat4 probe_xform, vec3 bounds,vec3 cell_s
|
||||
|
||||
//irradiance
|
||||
|
||||
vec3 irr_light = voxel_cone_trace(probe,cell_size,probe_pos,environment,blend_ambient,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,max(min_ref_tan,tan(roughness * 0.5 * M_PI)) ,max_distance);
|
||||
|
||||
irr_light *= multiplier;
|
||||
//irr_light=vec3(0.0);
|
||||
|
||||
Reference in New Issue
Block a user