Render Simplification

This adds a few settings to control global render quality, for faster
renders when tweaking lighting etc. The implementation is not so great,
and this should really be part of a proper render profile and preset
system. So for now it's a hidden Peach feature, enabled by setting rt
to 1. Before the next release, I'll either remove or improve it.

Settings are:

- Maximum subsurf level
- Child particles percentage
- Maximum shadow map samples
- AO and SSS quality factor
This commit is contained in:
Brecht Van Lommel 2008-02-13 11:18:08 +00:00
parent 3192263367
commit b12793fb4f
13 changed files with 136 additions and 31 deletions

@ -41,6 +41,7 @@ struct Base;
struct AviCodecData;
struct QuicktimeCodecData;
struct SculptData;
struct RenderData;
/* sequence related defines */
#define WHILE_SEQ(base) { \
@ -82,5 +83,11 @@ void scene_update_for_newframe(struct Scene *sce, unsigned int lay);
void scene_add_render_layer(struct Scene *sce);
/* render profile */
int get_render_subsurf_level(struct RenderData *r, int level);
int get_render_child_particle_number(struct RenderData *r, int num);
int get_render_shadow_samples(struct RenderData *r, int samples);
float get_render_aosss_error(struct RenderData *r, float error);
#endif

@ -63,7 +63,6 @@
#include "BKE_bad_level_calls.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_displist.h"
#include "BKE_particle.h"
#include "BKE_global.h"
#include "BKE_utildefines.h"
@ -77,6 +76,7 @@
#include "BKE_pointcache.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_scene.h"
#include "BSE_headerbuttons.h"
@ -145,15 +145,24 @@ static void alloc_particles(Object *ob, ParticleSystem *psys, int new_totpart)
psys->totpart=totpart;
}
static int get_alloc_child_particles_tot(ParticleSystem *psys)
static int get_psys_child_number(ParticleSystem *psys)
{
int child_nbr;
int nbr;
if(!psys->part->childtype)
return 0;
child_nbr= (psys->renderdata)? psys->part->ren_child_nbr: psys->part->child_nbr;
return psys->totpart*child_nbr;
if(psys->renderdata) {
nbr= psys->part->ren_child_nbr;
return get_render_child_particle_number(&G.scene->r, nbr);
}
else
return psys->part->child_nbr;
}
static int get_psys_tot_child(ParticleSystem *psys)
{
return psys->totpart*get_psys_child_number(psys);
}
static void alloc_child_particles(ParticleSystem *psys, int tot)
@ -863,7 +872,7 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
BLI_kdtree_balance(tree);
totpart=get_alloc_child_particles_tot(psys);
totpart=get_psys_tot_child(psys);
cfrom=from=PART_FROM_FACE;
if(part->flag&PART_CHILD_SEAMS){
@ -912,9 +921,9 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
}
else{
/* no need to figure out distribution */
int child_nbr= (psys->renderdata)? part->ren_child_nbr: part->child_nbr;
int child_nbr= get_psys_child_number(psys);
totpart= get_alloc_child_particles_tot(psys);
totpart= get_psys_tot_child(psys);
alloc_child_particles(psys, totpart);
cpa=psys->child;
for(i=0; i<child_nbr; i++){
@ -4219,9 +4228,8 @@ static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd,
ParticleSettings *part=psys->part;
ParticleEditSettings *pset=&G.scene->toolsettings->particle;
int distr=0,alloc=0;
int child_nbr= (psys->renderdata)? part->ren_child_nbr: part->child_nbr;
if((psys->part->childtype && psys->totchild != psys->totpart*child_nbr) || psys->recalc&PSYS_ALLOC)
if((psys->part->childtype && psys->totchild != get_psys_tot_child(psys)) || psys->recalc&PSYS_ALLOC)
alloc=1;
if(alloc || psys->recalc&PSYS_DISTR || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT)))
@ -4231,7 +4239,7 @@ static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd,
if(alloc)
alloc_particles(ob,psys,psys->totpart);
if(get_alloc_child_particles_tot(psys)) {
if(get_psys_tot_child(psys)) {
/* don't generate children while computing the hair keys */
if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
distribute_particles(ob,psys,PART_FROM_CHILD);
@ -4386,7 +4394,6 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
int totpart,oldtotpart=0,p;
float disp, *vg_vel=0, *vg_tan=0, *vg_rot=0, *vg_size=0;
int init=0,distr=0,alloc=0;
int child_nbr;
/*----start validity checks----*/
@ -4457,8 +4464,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
else
totpart = psys->part->totpart;
child_nbr= (psys->renderdata)? part->ren_child_nbr: part->child_nbr;
if(oldtotpart != totpart || psys->recalc&PSYS_ALLOC || (psys->part->childtype && psys->totchild != psys->totpart*child_nbr))
if(oldtotpart != totpart || psys->recalc&PSYS_ALLOC || (psys->part->childtype && psys->totchild != get_psys_tot_child(psys)))
alloc = 1;
if(alloc || psys->recalc&PSYS_DISTR || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT) && ob==OBACT))
@ -4477,7 +4483,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE))
/* don't generate children while growing hair - waste of time */
psys_free_children(psys);
else if(get_alloc_child_particles_tot(psys))
else if(get_psys_tot_child(psys))
distribute_particles(ob, psys, PART_FROM_CHILD);
}
initialize_all_particles(ob, psys, psmd);

@ -220,6 +220,11 @@ Scene *add_scene(char *name)
sce->r.stereomode = 1; // no stereo
sce->r.simplify_subsurf= 6;
sce->r.simplify_particles= 1.0f;
sce->r.simplify_shadowsamples= 16;
sce->r.simplify_aosss= 1.0f;
sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings),"Tool Settings Struct");
sce->toolsettings->cornertype=1;
sce->toolsettings->degr = 90;
@ -701,3 +706,38 @@ void sculpt_reset_curve(SculptData *sd)
curvemapping_changed(sd->cumap, 0);
}
/* render simplification */
int get_render_subsurf_level(RenderData *r, int lvl)
{
if(G.rt == 1 && (r->mode & R_SIMPLIFY))
return MIN2(r->simplify_subsurf, lvl);
else
return lvl;
}
int get_render_child_particle_number(RenderData *r, int num)
{
if(G.rt == 1 && (r->mode & R_SIMPLIFY))
return (int)(r->simplify_particles*num);
else
return num;
}
int get_render_shadow_samples(RenderData *r, int samples)
{
if(G.rt == 1 && (r->mode & R_SIMPLIFY) && samples > 0)
return MIN2(r->simplify_shadowsamples, samples);
else
return samples;
}
float get_render_aosss_error(RenderData *r, float error)
{
if(G.rt == 1 && (r->mode & R_SIMPLIFY))
return ((1.0f-r->simplify_aosss)*10.0f + 1.0f)*error;
else
return error;
}

@ -42,16 +42,18 @@
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_bad_level_calls.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_utildefines.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_scene.h"
#include "BKE_subsurf.h"
#include "BKE_displist.h"
#include "BKE_DerivedMesh.h"
#include "BLI_blenlib.h"
#include "BLI_editVert.h"
@ -2421,7 +2423,14 @@ struct DerivedMesh *subsurf_make_derived_from_derived(
useSubsurfUv, dm);
} else if(useRenderParams) {
/* Do not use cache in render mode. */
CCGSubSurf *ss = _getSubSurf(NULL, smd->renderLevels, 0, 1, useSimple);
CCGSubSurf *ss;
int levels;
levels= get_render_subsurf_level(&G.scene->r, smd->renderLevels);
if(levels == 0)
return dm;
ss = _getSubSurf(NULL, levels, 0, 1, useSimple);
ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);

@ -7007,10 +7007,18 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
wrld->ao_approx_error= 0.25f;
}
for(sce= main->scene.first; sce; sce= sce->id.next)
for(sce= main->scene.first; sce; sce= sce->id.next) {
if(sce->nodetree)
ntree_version_245(sce->nodetree);
if(sce->r.simplify_shadowsamples == 0) {
sce->r.simplify_subsurf= 6;
sce->r.simplify_particles= 1.0f;
sce->r.simplify_shadowsamples= 16;
sce->r.simplify_aosss= 1.0f;
}
}
for(ntree=main->nodetree.first; ntree; ntree= ntree->id.next)
ntree_version_245(ntree);

@ -298,6 +298,12 @@ typedef struct RenderData {
/* foreground/background color. */
float fg_stamp[4];
float bg_stamp[4];
/* render simplify */
int simplify_subsurf;
int simplify_shadowsamples;
float simplify_particles;
float simplify_aosss;
} RenderData;
@ -558,6 +564,7 @@ typedef struct Scene {
#define R_SSS 0x200000
#define R_NO_OVERWRITE 0x400000 /* skip existing files */
#define R_TOUCH 0x800000 /* touch files before rendering */
#define R_SIMPLIFY 0x1000000
/* filtertype */

@ -57,7 +57,7 @@ void threaded_makeshadowbufs(struct Render *re);
* @param inp The inproduct between viewvector and ?
*
*/
float testshadowbuf(struct ShadBuf *shb, float *rco, float *dxco, float *dyco, float inp, float mat_bias);
float testshadowbuf(struct Render *re, struct ShadBuf *shb, float *rco, float *dxco, float *dyco, float inp, float mat_bias);
/**
* Determines the shadow factor for lamp <lar>, between <p1>

@ -42,6 +42,7 @@
#include "BLI_threads.h"
#include "BKE_global.h"
#include "BKE_scene.h"
#include "BKE_utildefines.h"
#include "RE_shader_ext.h"
@ -650,7 +651,7 @@ static OcclusionTree *occ_tree_build(Render *re)
tree->totface= totface;
/* parameters */
tree->error= re->wrld.ao_approx_error;
tree->error= get_render_aosss_error(&re->r, re->wrld.ao_approx_error);
tree->distfac= (re->wrld.aomode & WO_AODIST)? re->wrld.aodistfac: 0.0f;
/* allocation */

@ -182,7 +182,7 @@ static void render_lighting_halo(HaloRen *har, float *colf)
inp= vn[0]*lv[0] + vn[1]*lv[1] + vn[2]*lv[2];
if(inp>0.0) {
/* testshadowbuf==0.0 : 100% shadow */
shadfac = testshadowbuf(lar->shb, rco, dco, dco, inp, 0.0f);
shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f);
if( shadfac>0.0 ) {
shadfac*= inp*soft*lar->energy;
ir -= shadfac;
@ -219,7 +219,7 @@ static void render_lighting_halo(HaloRen *har, float *colf)
if(i> -0.41) { /* heuristic valua! */
shadfac= 1.0;
if(lar->shb) {
shadfac = testshadowbuf(lar->shb, rco, dco, dco, inp, 0.0f);
shadfac = testshadowbuf(&R, lar->shb, rco, dco, dco, inp, 0.0f);
if(shadfac==0.0) continue;
i*= shadfac;
}

@ -34,6 +34,7 @@
#include "DNA_material_types.h"
#include "BKE_global.h"
#include "BKE_scene.h"
#include "BKE_utildefines.h"
#include "BLI_arithb.h"
@ -140,10 +141,11 @@ static float *give_jitter_tab(int samp)
}
static void make_jitter_weight_tab(ShadBuf *shb, short filtertype)
static void make_jitter_weight_tab(Render *re, ShadBuf *shb, short filtertype)
{
float *jit, totw= 0.0f;
int a, tot=shb->samp*shb->samp;
int samp= get_render_shadow_samples(&re->r, shb->samp);
int a, tot=samp*samp;
shb->weight= MEM_mallocN(sizeof(float)*tot, "weight tab lamp");
@ -406,8 +408,8 @@ void makeshadowbuf(Render *re, LampRen *lar)
if(ELEM(lar->buftype, LA_SHADBUF_REGULAR, LA_SHADBUF_HALFWAY)) {
/* jitter, weights - not threadsafe! */
BLI_lock_thread(LOCK_CUSTOM1);
shb->jit= give_jitter_tab(shb->samp);
make_jitter_weight_tab(shb, lar->filtertype);
shb->jit= give_jitter_tab(get_render_shadow_samples(&re->r, shb->samp));
make_jitter_weight_tab(re, shb, lar->filtertype);
BLI_unlock_thread(LOCK_CUSTOM1);
shb->totbuf= lar->buffers;
@ -652,7 +654,7 @@ static float readshadowbuf(ShadBuf *shb, ShadSampleBuf *shsample, int bias, int
/* the externally called shadow testing (reading) function */
/* return 1.0: no shadow at all */
float testshadowbuf(ShadBuf *shb, float *rco, float *dxco, float *dyco, float inp, float mat_bias)
float testshadowbuf(Render *re, ShadBuf *shb, float *rco, float *dxco, float *dyco, float inp, float mat_bias)
{
ShadSampleBuf *shsample;
float fac, co[4], dx[3], dy[3], shadfac=0.0f;
@ -690,7 +692,8 @@ float testshadowbuf(ShadBuf *shb, float *rco, float *dxco, float *dyco, float in
zs= ((float)0x7FFFFFFF)*fac;
/* take num*num samples, increase area with fac */
num= shb->samp*shb->samp;
num= get_render_shadow_samples(&re->r, shb->samp);
num= num*num;
fac= shb->soft;
if(mat_bias!=0.0f) biasf= shb->bias*mat_bias;

@ -1059,7 +1059,7 @@ void lamp_get_shadow(LampRen *lar, ShadeInput *shi, float inp, float *shadfac, i
if(lar->buftype==LA_SHADBUF_IRREGULAR)
shadfac[3]= ISB_getshadow(shi, lar->shb);
else
shadfac[3] = testshadowbuf(lar->shb, shi->co, shi->dxco, shi->dyco, inp, shi->mat->lbias);
shadfac[3] = testshadowbuf(&R, lar->shb, shi->co, shi->dxco, shi->dyco, inp, shi->mat->lbias);
}
else if(lar->mode & LA_SHAD_RAY) {
ray_shadow(shi, lar, shadfac);

@ -59,6 +59,7 @@
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
#include "BKE_scene.h"
#include "BKE_utildefines.h"
/* this module */
@ -921,7 +922,8 @@ static void sss_create_tree_mat(Render *re, Material *mat)
float *col= mat->sss_col, *radius= mat->sss_radius;
float fw= mat->sss_front, bw= mat->sss_back;
float error = mat->sss_error;
error= get_render_aosss_error(&re->r, error);
if((re->r.scemode & R_PREVIEWBUTS) && error < 0.5f)
error= 0.5f;

@ -2103,6 +2103,27 @@ static void render_panel_bake(void)
uiDefButS(block, NUM, B_DIFF,"Margin:", 210,30,120,20,&G.scene->r.bake_filter, 0.0, 32.0, 0, 0, "Amount of pixels to extend the baked result with, as post process filter");
}
static void render_panel_simplify(void)
{
uiBlock *block;
block= uiNewBlock(&curarea->uiblocks, "render_panel_simplify", UI_EMBOSS, UI_HELV, curarea->win);
uiNewPanelTabbed("Render", "Render");
if(uiNewPanel(curarea, block, "Simplifcation", "Render", 320, 0, 318, 204)==0) return;
uiDefButBitI(block, TOG, R_SIMPLIFY, B_DIFF,"Render Simplification", 10,150,190,20, &G.scene->r.mode, 0, 0, 0, 0, "Enable simplification of scene");
uiBlockBeginAlign(block);
uiDefButI(block, NUM,B_DIFF, "Subsurf:", 10,120,190,20, &G.scene->r.simplify_subsurf, 0.0, 6.0, 0, 0, "Global maximum subsurf level percentage");
uiDefButF(block, NUM,B_DIFF, "Child Particles:", 10,100,190,20, &G.scene->r.simplify_particles, 0.0, 1.0, 0, 0, "Global child particle percentage");
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
uiDefButI(block, NUM,B_DIFF, "Shadow Samples:", 10,70,190,20, &G.scene->r.simplify_shadowsamples, 1.0, 16.0, 0, 0, "Global maximum shadow map samples");
uiDefButF(block, NUM,B_DIFF, "AO and SSS:", 10,50,190,20, &G.scene->r.simplify_aosss, 0.0, 1.0, 0, 0, "Global approximate AO and SSS quality factor");
uiBlockEndAlign(block);
}
static void render_panel_render(void)
{
uiBlock *block;
@ -2830,6 +2851,7 @@ void render_panels()
render_panel_output();
render_panel_layers();
render_panel_render();
if(G.rt == 1) render_panel_simplify();
render_panel_anim();
render_panel_bake();