So! Finally time to work on finishing render pipeline project.

This commit brings back:

- Field Render
- MBlur Render (old style)
- Border render with or without cropping

Note: Field Render is not supported in Compositor yet. Blurring or filter
will destroy field information.
Both MotionBlur as Field render are done before Compositing happens.

Fixes:

- The "Save Buffers" option only worked on single frame renders, not for
  Anim render.
- Found an un-initalized variable in Render initialize... this might have
  caused the unknown random crashes with render.

Code restructure:

Cleaned up names and calls throughout the pipeline, more clearly telling
what goes on in functions.
This is visible in the updated first image of the Wiki doc:
http://mediawiki.blender.org/index.php/BlenderDev/RenderPipeline
This commit is contained in:
2006-05-27 13:35:03 +00:00
parent dee16b9e3d
commit e5b39b69d1
12 changed files with 340 additions and 124 deletions

View File

@@ -74,6 +74,7 @@ struct Object *copy_object(struct Object *ob);
void expand_local_object(struct Object *ob); void expand_local_object(struct Object *ob);
void make_local_object(struct Object *ob); void make_local_object(struct Object *ob);
void set_mblur_offs(float blur); void set_mblur_offs(float blur);
void set_field_offs(float field);
void disable_speed_curve(int val); void disable_speed_curve(int val);
float bsystem_time(struct Object *ob, struct Object *par, float cfra, float ofs); float bsystem_time(struct Object *ob, struct Object *par, float cfra, float ofs);

View File

@@ -752,15 +752,11 @@ float get_action_frame_inv(Object *ob, float cframe)
static float nla_time(float cfra, float unit) static float nla_time(float cfra, float unit)
{ {
extern float bluroffs; // bad construct, borrowed from object.c for now extern float bluroffs; // bad construct, borrowed from object.c for now
extern float fieldoffs;
/* 2nd field */ /* motion blur & fields */
// if(R.flag & R_SEC_FIELD) { cfra+= unit*(bluroffs+fieldoffs);
// if(R.r.mode & R_FIELDSTILL); else cfra+= 0.5f*unit;
// }
/* motion blur */
cfra+= unit*bluroffs;
/* global time */ /* global time */
cfra*= G.scene->r.framelen; cfra*= G.scene->r.framelen;

View File

@@ -183,14 +183,12 @@ int fluidsim_ar[FLUIDSIM_TOTIPO]= {
float frame_to_float(int cfra) /* see also bsystem_time in object.c */ float frame_to_float(int cfra) /* see also bsystem_time in object.c */
{ {
extern float bluroffs; /* object.c */ extern float bluroffs; /* bad stuff borrowed from object.c */
extern float fieldoffs;
float ctime; float ctime;
ctime= (float)cfra; ctime= (float)cfra;
// if(R.flag & R_SEC_FIELD) { ctime+= bluroffs+fieldoffs;
// if((R.r.mode & R_FIELDSTILL)==0) ctime+= 0.5;
// }
ctime+= bluroffs;
ctime*= G.scene->r.framelen; ctime*= G.scene->r.framelen;
return ctime; return ctime;

View File

@@ -938,6 +938,9 @@ static void node_composit_exec_rresult(void *data, bNode *node, bNodeStack **in,
stackbuf->rect= rl->rectf; stackbuf->rect= rl->rectf;
} }
stackbuf->xof= rr->xof;
stackbuf->yof= rr->yof;
/* put on stack */ /* put on stack */
out[RRES_OUT_IMAGE]->data= stackbuf; out[RRES_OUT_IMAGE]->data= stackbuf;

View File

@@ -997,15 +997,20 @@ void make_local_object(Object *ob)
/* there is also a timing calculation in drawobject() */ /* there is also a timing calculation in drawobject() */
float bluroffs= 0.0; float bluroffs= 0.0f, fieldoffs= 0.0f;
int no_speed_curve= 0; int no_speed_curve= 0;
/* ugly call from render */ /* ugly calls from render */
void set_mblur_offs(float blur) void set_mblur_offs(float blur)
{ {
bluroffs= blur; bluroffs= blur;
} }
void set_field_offs(float field)
{
fieldoffs= field;
}
void disable_speed_curve(int val) void disable_speed_curve(int val)
{ {
no_speed_curve= val; no_speed_curve= val;
@@ -1016,12 +1021,7 @@ float bsystem_time(Object *ob, Object *par, float cfra, float ofs)
{ {
/* returns float ( see frame_to_float in ipo.c) */ /* returns float ( see frame_to_float in ipo.c) */
/* 2nd field */ cfra+= bluroffs+fieldoffs;
// if(R.flag & R_SEC_FIELD) {
// if(R.r.mode & R_FIELDSTILL); else cfra+= .5;
// }
cfra+= bluroffs;
/* global time */ /* global time */
cfra*= G.scene->r.framelen; cfra*= G.scene->r.framelen;

View File

@@ -414,7 +414,7 @@ typedef struct Scene {
#define R_RADIO 0x0100 #define R_RADIO 0x0100
#define R_BORDER 0x0200 #define R_BORDER 0x0200
#define R_PANORAMA 0x0400 #define R_PANORAMA 0x0400
/* was moviecrop 0x0800 */ #define R_CROP 0x0800
#define R_COSMO 0x1000 #define R_COSMO 0x1000
#define R_ODDFIELD 0x2000 #define R_ODDFIELD 0x2000
#define R_MBLUR 0x4000 #define R_MBLUR 0x4000

View File

@@ -93,6 +93,8 @@ typedef struct RenderResult {
/* coordinates within final image (after cropping) */ /* coordinates within final image (after cropping) */
rcti tilerect; rcti tilerect;
/* offset to apply to get a border render in full image */
int xof, yof;
/* the main buffers */ /* the main buffers */
ListBase layers; ListBase layers;

View File

@@ -347,7 +347,6 @@ typedef struct LampRen
#define R_HALO 2 #define R_HALO 2
#define R_SEC_FIELD 4 #define R_SEC_FIELD 4
#define R_LAMPHALO 8 #define R_LAMPHALO 8
#define R_FILEBUFFER 16
/* vlakren->flag (vlak = face in dutch) char!!! */ /* vlakren->flag (vlak = face in dutch) char!!! */
#define R_SMOOTH 1 #define R_SMOOTH 1

View File

@@ -464,6 +464,8 @@ void RE_SetCamera(Render *re, Object *camera)
/* question mark */ /* question mark */
re->ycor= ( (float)re->r.yasp)/( (float)re->r.xasp); re->ycor= ( (float)re->r.yasp)/( (float)re->r.xasp);
if(re->r.mode & R_FIELDS)
re->ycor *= 2.0f;
if(camera->type==OB_CAMERA) { if(camera->type==OB_CAMERA) {
cam= camera->data; cam= camera->data;
@@ -603,17 +605,19 @@ void initparts(Render *re)
xparts= re->r.xparts; xparts= re->r.xparts;
yparts= re->r.yparts; yparts= re->r.yparts;
/* mininum part size */ /* mininum part size, but for exr tile saving it was checked already */
if(re->r.mode & R_PANORAMA) { if(!(re->r.scemode & R_EXR_TILE_FILE)) {
if(re->rectx/xparts < 8) if(re->r.mode & R_PANORAMA) {
xparts= 1 + re->rectx/8; if(re->rectx/xparts < 8)
xparts= 1 + re->rectx/8;
}
else
if(re->rectx/xparts < 64)
xparts= 1 + re->rectx/64;
if(re->recty/yparts < 64)
yparts= 1 + re->recty/64;
} }
else
if(re->rectx/xparts < 64)
xparts= 1 + re->rectx/64;
if(re->recty/yparts < 64)
yparts= 1 + re->recty/64;
/* part size */ /* part size */
partx= re->rectx/xparts; partx= re->rectx/xparts;

View File

@@ -40,6 +40,7 @@
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_image.h" #include "BKE_image.h"
#include "BKE_node.h" #include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_scene.h" #include "BKE_scene.h"
#include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */ #include "BKE_writeavi.h" /* <------ should be replaced once with generic movie module */
@@ -286,8 +287,6 @@ static void render_unique_exr_name(Render *re, char *str)
else else
BLI_make_file_string("/", str, U.tempdir, name); BLI_make_file_string("/", str, U.tempdir, name);
printf("exr file %s\n", str);
} }
static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype) static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype)
@@ -342,11 +341,12 @@ RenderLayer *RE_GetRenderLayer(RenderResult *rr, const char *name)
return NULL; return NULL;
} }
#define RR_USEMEM 0
/* called by main render as well for parts */ /* called by main render as well for parts */
/* will read info from Render *re to define layers */ /* will read info from Render *re to define layers */
/* called in threads */ /* called in threads */
/* re->winx,winy is coordinate space of entire image, partrct the part within */ /* re->winx,winy is coordinate space of entire image, partrct the part within */
static RenderResult *new_render_result(Render *re, rcti *partrct, int crop) static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int savebuffers)
{ {
RenderResult *rr; RenderResult *rr;
RenderLayer *rl; RenderLayer *rl;
@@ -371,8 +371,7 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop)
rr->tilerect.ymin= partrct->ymin - re->disprect.ymin; rr->tilerect.ymin= partrct->ymin - re->disprect.ymin;
rr->tilerect.ymax= partrct->ymax - re->disprect.ymax; rr->tilerect.ymax= partrct->ymax - re->disprect.ymax;
/* this flag needs cleared immediate after result was made */ if(savebuffers) {
if(re->flag & R_FILEBUFFER) {
rr->exrhandle= IMB_exr_get_handle(); rr->exrhandle= IMB_exr_get_handle();
} }
@@ -434,16 +433,20 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop)
re->r.actlay= 0; re->r.actlay= 0;
} }
/* border render; calculate offset for use in compositor. compo is centralized coords */
rr->xof= re->disprect.xmin + (re->disprect.xmax - re->disprect.xmin)/2 - re->winx/2;
rr->yof= re->disprect.ymin + (re->disprect.ymax - re->disprect.ymin)/2 - re->winy/2;
return rr; return rr;
} }
static int render_result_needs_vector(Render *re) static int render_scene_needs_vector(Render *re)
{ {
if(re->r.scemode & R_DOCOMP) { if(re->r.scemode & R_DOCOMP) {
RenderLayer *rl; SceneRenderLayer *srl;
for(rl= re->result->layers.first; rl; rl= rl->next) for(srl= re->scene->r.layers.first; srl; srl= srl->next)
if(rl->passflag & SCE_PASS_VECTOR) if(srl->passflag & SCE_PASS_VECTOR)
return 1; return 1;
} }
return 0; return 0;
@@ -541,7 +544,6 @@ static void save_render_result_tile(Render *re, RenderPart *pa)
party= rrpart->tilerect.ymin + rrpart->crop; party= rrpart->tilerect.ymin + rrpart->crop;
partx= rrpart->tilerect.xmin + rrpart->crop; partx= rrpart->tilerect.xmin + rrpart->crop;
IMB_exrtile_write_channels(re->result->exrhandle, partx, party); IMB_exrtile_write_channels(re->result->exrhandle, partx, party);
BLI_unlock_thread(LOCK_CUSTOM1); BLI_unlock_thread(LOCK_CUSTOM1);
@@ -557,7 +559,7 @@ static void read_render_result(Render *re)
char str[FILE_MAXDIR+FILE_MAXFILE]; char str[FILE_MAXDIR+FILE_MAXFILE];
free_render_result(re->result); free_render_result(re->result);
re->result= new_render_result(re, &re->disprect, 0); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM);
render_unique_exr_name(re, str); render_unique_exr_name(re, str);
if(IMB_exr_begin_read(exrhandle, str, &rectx, &recty)==0) { if(IMB_exr_begin_read(exrhandle, str, &rectx, &recty)==0) {
@@ -762,7 +764,7 @@ void RE_InitState(Render *re, RenderData *rd, int winx, int winy, rcti *disprect
re->recty= disprect->ymax-disprect->ymin; re->recty= disprect->ymax-disprect->ymin;
} }
else { else {
re->disprect.xmin= re->disprect.xmax= 0; re->disprect.xmin= re->disprect.ymin= 0;
re->disprect.xmax= winx; re->disprect.xmax= winx;
re->disprect.ymax= winy; re->disprect.ymax= winy;
re->rectx= winx; re->rectx= winx;
@@ -784,8 +786,11 @@ void RE_InitState(Render *re, RenderData *rd, int winx, int winy, rcti *disprect
/* always call, checks for gamma, gamma tables and jitter too */ /* always call, checks for gamma, gamma tables and jitter too */
make_sample_tables(re); make_sample_tables(re);
/* make empty render result, so display callbacks can initialize */
free_render_result(re->result); free_render_result(re->result);
re->result= new_render_result(re, &re->disprect, 0); re->result= MEM_callocN(sizeof(RenderResult), "new render result");
re->result->rectx= re->rectx;
re->result->recty= re->recty;
} }
} }
@@ -797,7 +802,7 @@ void RE_SetDispRect (struct Render *re, rcti *disprect)
/* initialize render result */ /* initialize render result */
free_render_result(re->result); free_render_result(re->result);
re->result= new_render_result(re, &re->disprect, 0); re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM);
} }
void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend) void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend)
@@ -885,7 +890,7 @@ static void *do_part_thread(void *pa_v)
/* need to return nicely all parts on esc */ /* need to return nicely all parts on esc */
if(R.test_break()==0) { if(R.test_break()==0) {
pa->result= new_render_result(&R, &pa->disprect, pa->crop); pa->result= new_render_result(&R, &pa->disprect, pa->crop, RR_USEMEM);
if(R.osa) if(R.osa)
zbufshadeDA_tile(pa); zbufshadeDA_tile(pa);
@@ -904,13 +909,17 @@ static void *do_part_thread(void *pa_v)
return NULL; return NULL;
} }
/* returns with render result filled, not threaded */ /* returns with render result filled, not threaded, used for preview now only */
static void render_tile_processor(Render *re, int firsttile) static void render_tile_processor(Render *re, int firsttile)
{ {
RenderPart *pa; RenderPart *pa;
if(re->test_break()) if(re->test_break())
return; return;
/* first step; the entire render result, no exr saving here */
free_render_result(re->result);
re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM);
re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime; re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime;
re->stats_draw(&re->i); re->stats_draw(&re->i);
@@ -1068,10 +1077,14 @@ static void threaded_tile_processor(Render *re)
{ {
ListBase threads; ListBase threads;
RenderPart *pa, *nextpa; RenderPart *pa, *nextpa;
RenderResult *rr= re->result; RenderResult *rr;
rctf viewplane= re->viewplane; rctf viewplane= re->viewplane;
int maxthreads, rendering=1, counter= 1, drawtimer=0, hasdrawn, minx=0; int maxthreads, rendering=1, counter= 1, drawtimer=0, hasdrawn, minx=0;
/* first step; the entire render result, or prepare exr buffer saving */
free_render_result(re->result);
rr= re->result= new_render_result(re, &re->disprect, 0, re->r.scemode & R_EXR_TILE_FILE);
if(rr==NULL) if(rr==NULL)
return; return;
if(re->test_break()) if(re->test_break())
@@ -1082,6 +1095,8 @@ static void threaded_tile_processor(Render *re)
if(rr->exrhandle) { if(rr->exrhandle) {
char str[FILE_MAXDIR+FILE_MAXFILE]; char str[FILE_MAXDIR+FILE_MAXFILE];
render_unique_exr_name(re, str); render_unique_exr_name(re, str);
printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str);
IMB_exrtile_begin_write(rr->exrhandle, str, rr->rectx, rr->recty, rr->rectx/re->xparts, rr->recty/re->yparts); IMB_exrtile_begin_write(rr->exrhandle, str, rr->rectx, rr->recty, rr->rectx/re->xparts, rr->recty/re->yparts);
} }
@@ -1191,13 +1206,13 @@ void RE_TileProcessor(Render *re, int firsttile)
/* ************ This part uses API, for rendering Blender scenes ********** */ /* ************ This part uses API, for rendering Blender scenes ********** */
void render_one_frame(Render *re) static void do_render_3d(Render *re)
{ {
// re->cfra= cfra; /* <- unused! */ // re->cfra= cfra; /* <- unused! */
/* make render verts/faces/halos/lamps */ /* make render verts/faces/halos/lamps */
if(render_result_needs_vector(re)) if(render_scene_needs_vector(re))
RE_Database_FromScene_Vectors(re, re->scene); RE_Database_FromScene_Vectors(re, re->scene);
else else
RE_Database_FromScene(re, re->scene, 1); RE_Database_FromScene(re, re->scene, 1);
@@ -1208,19 +1223,221 @@ void render_one_frame(Render *re)
RE_Database_Free(re); RE_Database_Free(re);
} }
#if 0 /* called by blur loop, accumulate renderlayers */
/* accumulates osa frames */ static void addblur_rect(RenderResult *rr, float *rectf, float *rectf1, float blurfac, int channels)
static void do_render_blurred(Render *re, float frame)
{ {
float mfac= 1.0f - blurfac;
int a, b, stride= channels*rr->rectx;
int len= stride*sizeof(float);
for(a=0; a<rr->recty; a++) {
if(blurfac==1.0f) {
memcpy(rectf, rectf1, len);
}
else {
float *rf= rectf, *rf1= rectf1;
for( b= rr->rectx*channels; b>0; b--, rf++, rf1++) {
rf[0]= mfac*rf[0] + blurfac*rf1[0];
}
}
rectf+= stride;
rectf1+= stride;
}
} }
/* interleaves 2 frames */ /* called by blur loop, accumulate renderlayers */
static void do_render_fields(Render *re) static void merge_renderresult_blur(RenderResult *rr, RenderResult *brr, float blurfac)
{ {
RenderLayer *rl, *rl1;
RenderPass *rpass, *rpass1;
rl1= brr->layers.first;
for(rl= rr->layers.first; rl && rl1; rl= rl->next, rl1= rl1->next) {
/* combined */
if(rl->rectf && rl1->rectf)
addblur_rect(rr, rl->rectf, rl1->rectf, blurfac, 4);
/* passes are allocated in sync */
rpass1= rl1->passes.first;
for(rpass= rl->passes.first; rpass && rpass1; rpass= rpass->next, rpass1= rpass1->next) {
addblur_rect(rr, rpass->rect, rpass1->rect, blurfac, rpass->channels);
}
}
} }
#endif
/* main blur loop, can be called by fields too */
static void do_render_blur_3d(Render *re)
{
RenderResult *rres;
float blurfac;
int blur= re->r.osa;
/* create accumulation render result */
rres= new_render_result(re, &re->disprect, 0, RR_USEMEM);
/* do the blur steps */
while(blur--) {
set_mblur_offs( re->r.blurfac*((float)(re->r.osa-blur))/(float)re->r.osa );
do_render_3d(re);
blurfac= 1.0f/(float)(re->r.osa-blur);
merge_renderresult_blur(rres, re->result, blurfac);
if(re->test_break()) break;
}
/* swap results */
free_render_result(re->result);
re->result= rres;
set_mblur_offs(0.0f);
/* weak... the display callback wants an active renderlayer pointer... */
re->result->renlay= render_get_active_layer(re, re->result);
re->display_draw(re->result, NULL);
}
/* function assumes rectf1 and rectf2 to be half size of rectf */
static void interleave_rect(RenderResult *rr, float *rectf, float *rectf1, float *rectf2, int channels)
{
int a, stride= channels*rr->rectx;
int len= stride*sizeof(float);
for(a=0; a<rr->recty; a+=2) {
memcpy(rectf, rectf1, len);
rectf+= stride;
rectf1+= stride;
memcpy(rectf, rectf2, len);
rectf+= stride;
rectf2+= stride;
}
}
/* merge render results of 2 fields */
static void merge_renderresult_fields(RenderResult *rr, RenderResult *rr1, RenderResult *rr2)
{
RenderLayer *rl, *rl1, *rl2;
RenderPass *rpass, *rpass1, *rpass2;
rl1= rr1->layers.first;
rl2= rr2->layers.first;
for(rl= rr->layers.first; rl && rl1 && rl2; rl= rl->next, rl1= rl1->next, rl2= rl2->next) {
/* combined */
if(rl->rectf && rl1->rectf && rl2->rectf)
interleave_rect(rr, rl->rectf, rl1->rectf, rl2->rectf, 4);
/* passes are allocated in sync */
rpass1= rl1->passes.first;
rpass2= rl2->passes.first;
for(rpass= rl->passes.first; rpass && rpass1 && rpass2; rpass= rpass->next, rpass1= rpass1->next, rpass2= rpass2->next) {
interleave_rect(rr, rpass->rect, rpass1->rect, rpass2->rect, rpass->channels);
}
}
}
/* interleaves 2 frames */
static void do_render_fields_3d(Render *re)
{
RenderResult *rr1, *rr2= NULL;
/* no render result was created, we can safely halve render y */
re->winy /= 2;
re->recty /= 2;
re->disprect.ymin /= 2;
re->disprect.ymax /= 2;
/* first field, we have to call camera routine for correct aspect and subpixel offset */
RE_SetCamera(re, re->scene->camera);
if(re->r.mode & R_MBLUR)
do_render_blur_3d(re);
else
do_render_3d(re);
rr1= re->result;
re->result= NULL;
/* second field */
if(!re->test_break()) {
re->flag |= R_SEC_FIELD;
if((re->r.mode & R_FIELDSTILL)==0)
set_field_offs(0.5f);
RE_SetCamera(re, re->scene->camera);
if(re->r.mode & R_MBLUR)
do_render_blur_3d(re);
else
do_render_3d(re);
re->flag &= ~R_SEC_FIELD;
set_field_offs(0.0f);
rr2= re->result;
}
/* allocate original height new buffers */
re->winy *= 2;
re->recty *= 2;
re->disprect.ymin *= 2;
re->disprect.ymax *= 2;
re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM);
if(rr2) {
if(re->r.mode & R_ODDFIELD)
merge_renderresult_fields(re->result, rr2, rr1);
else
merge_renderresult_fields(re->result, rr1, rr2);
free_render_result(rr2);
}
free_render_result(rr1);
/* weak... the display callback wants an active renderlayer pointer... */
re->result->renlay= render_get_active_layer(re, re->result);
re->display_draw(re->result, NULL);
}
/* main render routine, no compositing */
static void do_render_fields_blur_3d(Render *re)
{
if(re->r.mode & R_FIELDS)
do_render_fields_3d(re);
else if(re->r.mode & R_MBLUR)
do_render_blur_3d(re);
else
do_render_3d(re);
/* when border render, check if we have to insert it in black */
if(re->result) {
if(re->r.mode & R_BORDER) {
if((re->r.mode & R_CROP)==0) {
RenderResult *rres;
/* sub-rect for merge call later on */
re->result->tilerect= re->disprect;
/* this copying sequence could become function? */
re->disprect.xmin= re->disprect.ymin= 0;
re->disprect.xmax= re->winx;
re->disprect.ymax= re->winy;
re->rectx= re->winx;
re->recty= re->winy;
rres= new_render_result(re, &re->disprect, 0, RR_USEMEM);
merge_render_result(rres, re->result);
free_render_result(re->result);
re->result= rres;
re->display_init(re->result);
re->display_draw(re->result, NULL);
}
}
}
}
/* within context of current Render *re, render another scene. /* within context of current Render *re, render another scene.
it uses current render image size and disprect, but doesn't execute composite it uses current render image size and disprect, but doesn't execute composite
@@ -1230,13 +1447,9 @@ static void render_scene(Render *re, Scene *sce, int cfra)
Render *resc= RE_NewRender(sce->id.name); Render *resc= RE_NewRender(sce->id.name);
sce->r.cfra= cfra; sce->r.cfra= cfra;
if(re->scene->r.scemode & R_EXR_TILE_FILE) /* initial setup */
resc->flag |= R_FILEBUFFER;
/* makes render result etc */
RE_InitState(resc, &sce->r, re->winx, re->winy, &re->disprect); RE_InitState(resc, &sce->r, re->winx, re->winy, &re->disprect);
resc->flag &= ~R_FILEBUFFER;
/* this to enable this scene to create speed vectors */ /* this to enable this scene to create speed vectors */
resc->r.scemode |= R_DOCOMP; resc->r.scemode |= R_DOCOMP;
@@ -1256,13 +1469,7 @@ static void render_scene(Render *re, Scene *sce, int cfra)
resc->test_break= re->test_break; resc->test_break= re->test_break;
resc->stats_draw= re->stats_draw; resc->stats_draw= re->stats_draw;
if(resc->r.mode & R_FIELDS) do_render_fields_blur_3d(resc);
printf("No field render yet...\n"); //do_render_fields(resc);
else if(resc->r.mode & R_MBLUR)
printf("No mblur render yet...\n"); //do_render_blurred(resc, resc->r.cfra);
//else
render_one_frame(resc);
} }
static void ntree_render_scenes(Render *re) static void ntree_render_scenes(Render *re)
@@ -1304,7 +1511,7 @@ static void ntree_render_scenes(Render *re)
} }
/* helper call to detect if theres a composite with render-result node */ /* helper call to detect if theres a composite with render-result node */
int composite_needs_render(Scene *sce) static int composite_needs_render(Scene *sce)
{ {
bNodeTree *ntree= sce->nodetree; bNodeTree *ntree= sce->nodetree;
bNode *node; bNode *node;
@@ -1329,60 +1536,49 @@ static void render_composit_stats(char *str)
R.i.infostr= NULL; R.i.infostr= NULL;
} }
static void do_render_final(Render *re) /* returns fully composited render-result on given time step (in RenderData) */
static void do_render_composite_fields_blur_3d(Render *re)
{ {
bNodeTree *ntree= re->scene->nodetree;
/* we set start time here, for main Blender loops */ /* we set start time here, for main Blender loops */
re->i.starttime= PIL_check_seconds_timer(); re->i.starttime= PIL_check_seconds_timer();
if(re->r.scemode & R_DOSEQ) { if(composite_needs_render(re->scene)) {
if(!re->test_break()) /* save memory... free all cached images */
do_render_seq(re->result, re->r.cfra); ntreeFreeCache(ntree);
/* now use renderdata and camera to set viewplane */
RE_SetCamera(re, re->scene->camera);
do_render_fields_blur_3d(re);
} }
else {
bNodeTree *ntree= re->scene->nodetree; /* swap render result */
if(re->r.scemode & R_SINGLE_LAYER)
pop_render_result(re);
if(!re->test_break() && ntree) {
ntreeCompositTagRender(ntree);
ntreeCompositTagAnimated(ntree);
if(composite_needs_render(re->scene)) { if(re->r.scemode & R_DOCOMP) {
/* save memory... free all cached images */ /* checks if there are render-result nodes that need scene */
ntreeFreeCache(ntree); if((re->r.scemode & R_SINGLE_LAYER)==0)
ntree_render_scenes(re);
/* now use renderdata and camera to set viewplane */ if(!re->test_break()) {
RE_SetCamera(re, re->scene->camera); ntree->stats_draw= render_composit_stats;
ntree->test_break= re->test_break;
if(re->r.mode & R_FIELDS) /* in case it was never initialized */
printf("No field render yet...\n"); //do_render_fields(resc); R.stats_draw= re->stats_draw;
else if(re->r.mode & R_MBLUR)
printf("No mblur render yet...\n"); //do_render_blurred(resc, resc->r.cfra);
//else
render_one_frame(re);
}
/* swap render result */
if(re->r.scemode & R_SINGLE_LAYER)
pop_render_result(re);
if(!re->test_break() && ntree) {
ntreeCompositTagRender(ntree);
ntreeCompositTagAnimated(ntree);
if(re->r.scemode & R_DOCOMP) {
/* checks if there are render-result nodes that need scene */
if((re->r.scemode & R_SINGLE_LAYER)==0)
ntree_render_scenes(re);
if(!re->test_break()) { ntreeCompositExecTree(ntree, &re->r, G.background==0);
ntree->stats_draw= render_composit_stats; ntree->stats_draw= NULL;
ntree->test_break= re->test_break; ntree->test_break= NULL;
/* in case it was never initialized */
R.stats_draw= re->stats_draw;
ntreeCompositExecTree(ntree, &re->r, G.background==0);
ntree->stats_draw= NULL;
ntree->test_break= NULL;
}
} }
} }
} }
re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime; re->i.lastframetime= PIL_check_seconds_timer()- re->i.starttime;
re->stats_draw(&re->i); re->stats_draw(&re->i);
@@ -1390,6 +1586,17 @@ static void do_render_final(Render *re)
re->display_draw(re->result, NULL); re->display_draw(re->result, NULL);
} }
/* main loop: doing sequence + fields + blur + 3d render + compositing */
static void do_render_all_options(Render *re)
{
if(re->r.scemode & R_DOSEQ) {
if(!re->test_break())
do_render_seq(re->result, re->r.cfra);
}
else {
do_render_composite_fields_blur_3d(re);
}
}
static int is_rendering_allowed(Render *re) static int is_rendering_allowed(Render *re)
{ {
@@ -1460,7 +1667,7 @@ static int render_initialize_from_scene(Render *re, Scene *scene)
winx= (scene->r.size*scene->r.xsch)/100; winx= (scene->r.size*scene->r.xsch)/100;
winy= (scene->r.size*scene->r.ysch)/100; winy= (scene->r.size*scene->r.ysch)/100;
/* only in movie case we render smaller part */ /* we always render smaller part, inserting it in larger image is compositor bizz, it uses disprect for it */
if(scene->r.mode & R_BORDER) { if(scene->r.mode & R_BORDER) {
disprect.xmin= scene->r.border.xmin*winx; disprect.xmin= scene->r.border.xmin*winx;
disprect.xmax= scene->r.border.xmax*winx; disprect.xmax= scene->r.border.xmax*winx;
@@ -1476,19 +1683,22 @@ static int render_initialize_from_scene(Render *re, Scene *scene)
if(scene->r.scemode & R_EXR_TILE_FILE) { if(scene->r.scemode & R_EXR_TILE_FILE) {
int partx= winx/scene->r.xparts, party= winy/scene->r.yparts; int partx= winx/scene->r.xparts, party= winy/scene->r.yparts;
/* stupid exr tiles dont like different sizes */ /* stupid exr tiles dont like different sizes */
if(winx != partx*scene->r.xparts || winy != party*scene->r.yparts) { if(winx != partx*scene->r.xparts || winy != party*scene->r.yparts) {
re->error("Sorry... exr tile saving only allowed with equally sized parts"); re->error("Sorry... exr tile saving only allowed with equally sized parts");
return 0; return 0;
} }
re->flag |= R_FILEBUFFER; if((scene->r.mode & R_FIELDS) && (party & 1)) {
re->error("Sorry... exr tile saving only allowed with equally sized parts");
return 0;
}
} }
if(scene->r.scemode & R_SINGLE_LAYER) if(scene->r.scemode & R_SINGLE_LAYER)
push_render_result(re); push_render_result(re);
RE_InitState(re, &scene->r, winx, winy, &disprect); RE_InitState(re, &scene->r, winx, winy, &disprect);
re->flag &= ~R_FILEBUFFER;
re->scene= scene; re->scene= scene;
if(!is_rendering_allowed(re)) if(!is_rendering_allowed(re))
@@ -1510,7 +1720,7 @@ void RE_BlenderFrame(Render *re, Scene *scene, int frame)
scene->r.cfra= frame; scene->r.cfra= frame;
if(render_initialize_from_scene(re, scene)) { if(render_initialize_from_scene(re, scene)) {
do_render_final(re); do_render_all_options(re);
} }
/* UGLY WARNING */ /* UGLY WARNING */
@@ -1604,7 +1814,7 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra)
scene->r.cfra = nf; scene->r.cfra = nf;
re->r.cfra= scene->r.cfra; /* weak.... */ re->r.cfra= scene->r.cfra; /* weak.... */
do_render_final(re); do_render_all_options(re);
if(re->test_break() == 0) { if(re->test_break() == 0) {
do_write_image_or_movie(re, scene, mh); do_write_image_or_movie(re, scene, mh);
@@ -1616,7 +1826,7 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra)
scene->r.cfra<=efra; scene->r.cfra++) { scene->r.cfra<=efra; scene->r.cfra++) {
re->r.cfra= scene->r.cfra; /* weak.... */ re->r.cfra= scene->r.cfra; /* weak.... */
do_render_final(re); do_render_all_options(re);
if(re->test_break() == 0) { if(re->test_break() == 0) {
do_write_image_or_movie(re, scene, mh); do_write_image_or_movie(re, scene, mh);

View File

@@ -1506,7 +1506,8 @@ static void render_panel_format(void)
uiDefButBitI(block, TOG, R_COSMO, 0,"Cosmo", 1059,32,60,20, &G.scene->r.mode, 0, 0, 0, 0, "Attempt to save SGI movies using Cosmo hardware"); uiDefButBitI(block, TOG, R_COSMO, 0,"Cosmo", 1059,32,60,20, &G.scene->r.mode, 0, 0, 0, 0, "Attempt to save SGI movies using Cosmo hardware");
#endif #endif
uiDefButS(block, MENU,B_FILETYPEMENU,imagetype_pup(), 892,yofs,225,20, &G.scene->r.imtype, 0, 0, 0, 0, "Images are saved in this file format"); uiDefButS(block, MENU,B_FILETYPEMENU,imagetype_pup(), 892,yofs,174,20, &G.scene->r.imtype, 0, 0, 0, 0, "Images are saved in this file format");
uiDefButBitI(block, TOG, R_CROP, B_DIFF, "Crop", 1068,yofs,51,20, &G.scene->r.mode, 0, 0, 0, 0, "When Border render, the resulting image gets cropped");
yofs -= 22; yofs -= 22;

View File

@@ -218,9 +218,11 @@ void save_image_filesel_str(char *str)
/* calls fileselect if zbuf is set we are rendering the zbuffer */ /* calls fileselect if zbuf is set we are rendering the zbuffer */
void BIF_save_rendered_image_fs(int zbuf) void BIF_save_rendered_image_fs(int zbuf)
{ {
RenderResult *rr= RE_GetResult(RE_GetRender(G.scene->id.name)); RenderResult rres;
if(!rr) { RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres);
if(!rres.rectf) {
error("No image rendered"); error("No image rendered");
} else { } else {
char dir[FILE_MAXDIR * 2], str[FILE_MAXFILE * 2]; char dir[FILE_MAXDIR * 2], str[FILE_MAXFILE * 2];