Files
test/source/blender/render/intern/source/shadeinput.c

1495 lines
42 KiB
C
Raw Normal View History

/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
2010-02-12 13:34:04 +00:00
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2006 Blender Foundation
* All rights reserved.
*
* Contributors: Hos, Robert Wenzlaff.
*
* ***** END GPL LICENSE BLOCK *****
*/
2011-02-27 19:31:27 +00:00
/** \file blender/render/intern/source/shadeinput.c
* \ingroup render
*/
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "DNA_lamp_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_material_types.h"
#include "DNA_particle_types.h"
#include "BKE_scene.h"
#include "BKE_node.h"
/* local include */
#include "raycounter.h"
#include "render_types.h"
#include "renderdatabase.h"
#include "rendercore.h"
#include "shading.h"
#include "strand.h"
#include "texture.h"
Voxel data & volume light cache * Added support for additional file types in the voxel data texture. I added support for 8 bit raw files, but most notably for image sequences. Image sequences generate the voxel grid by stacking layers of image slices on top of each other to generate the voxels in the Z axis - the number of slices in the sequence is the resolution of the voxel grid's Z axis. i.e. http://mke3.net/blender/devel/rendering/volumetrics/skull_layers.jpg The image sequence option is particularly useful for loading medical data into Blender. 3d medical data such as MRIs or CT scans are often stored as DICOM format image sequences. It's not in Blender's scope to support the DICOM format, but there are plenty of utilities such as ImageMagick, Photoshop or OsiriX that can easily convert DICOM files to formats that Blender supports, such as PNG or JPEG. Here are some example renderings using these file formats to load medical data: http://vimeo.com/5242961 http://vimeo.com/5242989 http://vimeo.com/5243228 Currently the 8 bit raw and image sequence formats only support the 'still' rendering feature. * Changed the default texture placement to be centred around 0.5,0.5,0.5, rather than within the 0.0,1.0 cube. This is more consistent with image textures, and it also means you can easily add a voxel data texture to a default cube without having to mess around with mapping. * Added some more extrapolation modes such as Repeat and Extend rather than just clipping http://mke3.net/blender/devel/rendering/volumetrics/bradybunch.jpg * Changed the voxel data storage to use MEM_Mapalloc (memory mapped disk cache) rather than storing in ram, to help cut down memory usage. * Refactored and cleaned up the code a lot. Now the access and interpolation code is separated into a separate voxel library inside blenlib. This is now properly shared between voxel data texture and light cache (previously there was some duplicated code). * Made volume light cache support non-cubic voxel grids. Now the resolution specified in the material properties is used for the longest edge of the volume object's bounding box, and the shorter edges are proportional (similar to how resolution is calculated for fluid sim domains). This is *much* more memory efficient for squashed volume regions like clouds layer bounding boxes, allowing you to raise the resolution considerably while still keeping memory usage acceptable.
2009-06-20 06:41:50 +00:00
#include "volumetric.h"
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
#include "zbuf.h"
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
/* only to be used here in this file, it's for speed */
extern struct Render R;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* Shade Sample order:
2012-03-09 18:28:30 +00:00
*
* - shade_samples_fill_with_ps()
* - for each sample
* - shade_input_set_triangle() <- if prev sample-face is same, use shade_input_copy_triangle()
* - if vlr
* - shade_input_set_viewco() <- not for ray or bake
* - shade_input_set_uv() <- not for ray or bake
* - shade_input_set_normals()
* - shade_samples()
* - if AO
* - shade_samples_do_AO()
* - if shading happens
* - for each sample
* - shade_input_set_shade_texco()
* - shade_samples_do_shade()
* - OSA: distribute sample result with filter masking
*
*/
/* initialize material variables in shadeinput,
* doing inverse gamma correction where applicable */
void shade_input_init_material(ShadeInput *shi)
{
Changes to Color Management After testing and feedback, I've decided to slightly modify the way color management works internally. While the previous method worked well for rendering, was a smaller transition and had some advantages over this new method, it was a bit more ambiguous, and was making things difficult for other areas such as compositing. This implementation now considers all color data (with only a couple of exceptions such as brush colors) to be stored in linear RGB color space, rather than sRGB as previously. This brings it in line with Nuke, which also operates this way, quite successfully. Color swatches, pickers, color ramp display are now gamma corrected to display gamma so you can see what you're doing, but the numbers themselves are considered linear. This makes understanding blending modes more clear (a 0.5 value on overlay will not change the result now) as well as making color swatches act more predictably in the compositor, however bringing over color values from applications like photoshop or gimp, that operate in a gamma space, will give identical results. This commit will convert over existing files saved by earlier 2.5 versions to work generally the same, though there may be some slight differences with things like textures. Now that we're set on changing other areas of shading, this won't be too disruptive overall. I've made a diagram explaining the pipeline here: http://mke3.net/blender/devel/2.5/25_linear_workflow_pipeline.png and some docs here: http://www.blender.org/development/release-logs/blender-250/color-management/
2009-12-02 07:56:34 +00:00
/* note, keep this synced with render_types.h */
2012-07-08 21:37:59 +00:00
memcpy(&shi->r, &shi->mat->r, 23 * sizeof(float));
shi->har = shi->mat->har;
}
/* also used as callback for nodes */
/* delivers a fully filled in ShadeResult, for all passes */
void shade_material_loop(ShadeInput *shi, ShadeResult *shr)
{
Changes to Color Management After testing and feedback, I've decided to slightly modify the way color management works internally. While the previous method worked well for rendering, was a smaller transition and had some advantages over this new method, it was a bit more ambiguous, and was making things difficult for other areas such as compositing. This implementation now considers all color data (with only a couple of exceptions such as brush colors) to be stored in linear RGB color space, rather than sRGB as previously. This brings it in line with Nuke, which also operates this way, quite successfully. Color swatches, pickers, color ramp display are now gamma corrected to display gamma so you can see what you're doing, but the numbers themselves are considered linear. This makes understanding blending modes more clear (a 0.5 value on overlay will not change the result now) as well as making color swatches act more predictably in the compositor, however bringing over color values from applications like photoshop or gimp, that operate in a gamma space, will give identical results. This commit will convert over existing files saved by earlier 2.5 versions to work generally the same, though there may be some slight differences with things like textures. Now that we're set on changing other areas of shading, this won't be too disruptive overall. I've made a diagram explaining the pipeline here: http://mke3.net/blender/devel/2.5/25_linear_workflow_pipeline.png and some docs here: http://www.blender.org/development/release-logs/blender-250/color-management/
2009-12-02 07:56:34 +00:00
2012-07-08 21:37:59 +00:00
shade_lamp_loop(shi, shr); /* clears shr */
2012-07-08 21:37:59 +00:00
if (shi->translucency != 0.0f) {
ShadeResult shr_t;
2012-07-08 21:37:59 +00:00
float fac = shi->translucency;
shade_input_init_material(shi);
negate_v3_v3(shi->vn, shi->vno);
negate_v3(shi->facenor);
2012-07-08 21:37:59 +00:00
shi->depth++; /* hack to get real shadow now */
shade_lamp_loop(shi, &shr_t);
shi->depth--;
/* a couple of passes */
madd_v3_v3fl(shr->combined, shr_t.combined, fac);
if (shi->passflag & SCE_PASS_SPEC)
madd_v3_v3fl(shr->spec, shr_t.spec, fac);
if (shi->passflag & SCE_PASS_DIFFUSE) {
madd_v3_v3fl(shr->diff, shr_t.diff, fac);
madd_v3_v3fl(shr->diffshad, shr_t.diffshad, fac);
}
if (shi->passflag & SCE_PASS_SHADOW)
madd_v3_v3fl(shr->shad, shr_t.shad, fac);
negate_v3(shi->vn);
negate_v3(shi->facenor);
}
/* depth >= 1 when ray-shading */
2012-07-08 21:37:59 +00:00
if (shi->depth == 0 || shi->volume_depth > 0) {
if (R.r.mode & R_RAYTRACE) {
2012-07-08 21:37:59 +00:00
if (shi->ray_mirror != 0.0f || ((shi->mode & MA_TRANSP) && (shi->mode & MA_RAYTRANSP) && shr->alpha != 1.0f)) {
/* ray trace works on combined, but gives pass info */
ray_trace(shi, shr);
}
}
/* disable adding of sky for raytransp */
if ((shi->mode & MA_TRANSP) && (shi->mode & MA_RAYTRANSP))
2012-07-08 21:37:59 +00:00
if ((shi->layflag & SCE_LAY_SKY) && (R.r.alphamode == R_ADDSKY))
shr->alpha = 1.0f;
}
if (R.r.mode & R_RAYTRACE) {
if (R.render_volumes_inside.first)
shade_volume_inside(shi, shr);
}
}
/* do a shade, finish up some passes, apply mist */
void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr)
{
bool compat = false;
float alpha;
/* ------ main shading loop -------- */
#ifdef RE_RAYCOUNTER
memset(&shi->raycounter, 0, sizeof(shi->raycounter));
#endif
if (shi->mat->nodetree && shi->mat->use_nodes) {
compat = ntreeShaderExecTree(shi->mat->nodetree, shi, shr);
}
/* also run this when node shaders fail, due to incompatible shader nodes */
if (compat == false) {
/* copy all relevant material vars, note, keep this synced with render_types.h */
shade_input_init_material(shi);
2009-08-23 22:11:19 +00:00
if (shi->mat->material_type == MA_TYPE_VOLUME) {
if (R.r.mode & R_RAYTRACE) {
shade_volume_outside(shi, shr);
}
}
else { /* MA_TYPE_SURFACE, MA_TYPE_WIRE */
2009-08-23 22:11:19 +00:00
shade_material_loop(shi, shr);
}
}
/* copy additional passes */
2012-07-08 21:37:59 +00:00
if (shi->passflag & (SCE_PASS_VECTOR | SCE_PASS_NORMAL)) {
copy_v4_v4(shr->winspeed, shi->winspeed);
copy_v3_v3(shr->nor, shi->vn);
}
/* MIST */
2012-07-08 21:37:59 +00:00
if ((shi->passflag & SCE_PASS_MIST) || ((R.wrld.mode & WO_MIST) && (shi->mat->mode & MA_NOMIST) == 0)) {
if (R.r.mode & R_ORTHO)
2012-07-08 21:37:59 +00:00
shr->mist = mistfactor(-shi->co[2], shi->co);
else
2012-07-08 21:37:59 +00:00
shr->mist = mistfactor(len_v3(shi->co), shi->co);
}
2012-07-08 21:37:59 +00:00
else shr->mist = 0.0f;
2012-07-08 21:37:59 +00:00
if ((R.wrld.mode & WO_MIST) && (shi->mat->mode & MA_NOMIST) == 0) {
alpha = shr->mist;
}
2012-07-08 21:37:59 +00:00
else alpha = 1.0f;
/* add mist and premul color */
2012-07-08 21:37:59 +00:00
if (shr->alpha != 1.0f || alpha != 1.0f) {
float fac = alpha * (shr->alpha);
shr->combined[3] = fac;
2012-07-08 21:37:59 +00:00
if (shi->mat->material_type != MA_TYPE_VOLUME)
mul_v3_fl(shr->combined, fac);
}
else
2012-07-08 21:37:59 +00:00
shr->combined[3] = 1.0f;
/* add z */
2012-07-08 21:37:59 +00:00
shr->z = -shi->co[2];
/* RAYHITS */
#if 0
if (1 || shi->passflag & SCE_PASS_RAYHITS) {
shr->rayhits[0] = (float)shi->raycounter.faces.test;
shr->rayhits[1] = (float)shi->raycounter.bb.hit;
shr->rayhits[2] = 0.0;
shr->rayhits[3] = 1.0;
}
#endif
2009-09-28 10:25:12 +00:00
RE_RC_MERGE(&re_rc_counter[shi->thread], &shi->raycounter);
}
/* **************************************************************************** */
/* ShadeInput */
/* **************************************************************************** */
void vlr_set_uv_indices(VlakRen *vlr, int *i1, int *i2, int *i3)
{
/* to prevent storing new tfaces or vcols, we check a split runtime */
/* 4---3 4---3 */
/* |\ 1| or |1 /| */
/* |0\ | |/ 0| */
/* 1---2 1---2 0 = orig face, 1 = new face */
/* Update vert nums to point to correct verts of original face */
if (vlr->flag & R_DIVIDE_24) {
if (vlr->flag & R_FACE_SPLIT) {
(*i1)++; (*i2)++; (*i3)++;
}
else {
(*i3)++;
}
}
else if (vlr->flag & R_FACE_SPLIT) {
(*i2)++; (*i3)++;
}
}
/* copy data from face to ShadeInput, general case */
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
/* indices 0 1 2 3 only */
void shade_input_set_triangle_i(ShadeInput *shi, ObjectInstanceRen *obi, VlakRen *vlr, short i1, short i2, short i3)
{
2012-07-08 21:37:59 +00:00
VertRen **vpp = &vlr->v1;
2012-07-08 21:37:59 +00:00
shi->vlr = vlr;
shi->obi = obi;
shi->obr = obi->obr;
2012-07-08 21:37:59 +00:00
shi->v1 = vpp[i1];
shi->v2 = vpp[i2];
shi->v3 = vpp[i3];
shi->i1 = i1;
shi->i2 = i2;
shi->i3 = i3;
/* note, shi->mat is set in node shaders */
2012-07-08 21:37:59 +00:00
shi->mat = shi->mat_override ? shi->mat_override : vlr->mat;
2012-07-08 21:37:59 +00:00
shi->osatex = (shi->mat->texco & TEXCO_OSA);
shi->mode = shi->mat->mode_l; /* or-ed result for all nodes */
shi->mode2 = shi->mat->mode2_l;
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
/* facenormal copy, can get flipped */
2012-07-08 21:37:59 +00:00
shi->flippednor = 0;
RE_vlakren_get_normal(&R, obi, vlr, shi->facenor);
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
/* calculate vertexnormals */
if (vlr->flag & R_SMOOTH) {
copy_v3_v3(shi->n1, shi->v1->n);
copy_v3_v3(shi->n2, shi->v2->n);
copy_v3_v3(shi->n3, shi->v3->n);
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
if (obi->flag & R_TRANSFORMED) {
mul_m3_v3(obi->nmat, shi->n1); normalize_v3(shi->n1);
mul_m3_v3(obi->nmat, shi->n2); normalize_v3(shi->n2);
mul_m3_v3(obi->nmat, shi->n3); normalize_v3(shi->n3);
}
}
}
/* note, facenr declared volatile due to over-eager -O2 optimization's
* on cygwin (particularly -frerun-cse-after-loop)
*/
/* copy data from face to ShadeInput, scanline case */
void shade_input_set_triangle(ShadeInput *shi, volatile int obi, volatile int facenr, int UNUSED(normal_flip))
{
2012-07-08 21:37:59 +00:00
if (facenr > 0) {
shi->obi = &R.objectinstance[obi];
shi->obr = shi->obi->obr;
shi->facenr = (facenr - 1) & RE_QUAD_MASK;
if (shi->facenr < shi->obr->totvlak) {
VlakRen *vlr = RE_findOrAddVlak(shi->obr, shi->facenr);
if (facenr & RE_QUAD_OFFS)
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
shade_input_set_triangle_i(shi, shi->obi, vlr, 0, 2, 3);
else
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
shade_input_set_triangle_i(shi, shi->obi, vlr, 0, 1, 2);
}
else
2012-07-08 21:37:59 +00:00
shi->vlr = NULL; /* general signal we got sky */
}
else
2012-07-08 21:37:59 +00:00
shi->vlr = NULL; /* general signal we got sky */
}
/* full osa case: copy static info */
void shade_input_copy_triangle(ShadeInput *shi, ShadeInput *from)
{
/* not so nice, but works... warning is in RE_shader_ext.h */
memcpy(shi, from, sizeof(struct ShadeInputCopy));
}
/* copy data from strand to shadeinput */
void shade_input_set_strand(ShadeInput *shi, StrandRen *strand, StrandPoint *spoint)
{
/* note, shi->mat is set in node shaders */
2012-07-08 21:37:59 +00:00
shi->mat = shi->mat_override ? shi->mat_override : strand->buffer->ma;
2012-07-08 21:37:59 +00:00
shi->osatex = (shi->mat->texco & TEXCO_OSA);
shi->mode = shi->mat->mode_l; /* or-ed result for all nodes */
/* shade_input_set_viewco equivalent */
copy_v3_v3(shi->co, spoint->co);
copy_v3_v3(shi->view, shi->co);
normalize_v3(shi->view);
2012-07-08 21:37:59 +00:00
shi->xs = (int)spoint->x;
shi->ys = (int)spoint->y;
if (shi->osatex || (R.r.mode & R_SHADOW)) {
copy_v3_v3(shi->dxco, spoint->dtco);
copy_v3_v3(shi->dyco, spoint->dsco);
}
/* dxview, dyview, not supported */
/* facenormal, simply viewco flipped */
copy_v3_v3(shi->facenor, spoint->nor);
/* shade_input_set_normals equivalent */
if (shi->mat->mode & MA_TANGENT_STR) {
copy_v3_v3(shi->vn, spoint->tan);
}
else {
float cross[3];
cross_v3_v3v3(cross, spoint->co, spoint->tan);
cross_v3_v3v3(shi->vn, cross, spoint->tan);
normalize_v3(shi->vn);
if (dot_v3v3(shi->vn, shi->view) < 0.0f)
negate_v3(shi->vn);
}
copy_v3_v3(shi->vno, shi->vn);
}
void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert *svert, StrandPoint *spoint)
{
2012-07-08 21:37:59 +00:00
StrandBuffer *strandbuf = strand->buffer;
ObjectRen *obr = strandbuf->obr;
StrandVert *sv;
2012-07-08 21:37:59 +00:00
int mode = shi->mode; /* or-ed result for all nodes */
short texco = shi->mat->texco;
if ((shi->mat->texco & TEXCO_REFL)) {
/* shi->dxview, shi->dyview, not supported */
}
2012-07-08 21:37:59 +00:00
if (shi->osatex && (texco & (TEXCO_NORM | TEXCO_REFL))) {
/* not supported */
}
2012-07-08 21:37:59 +00:00
if (mode & (MA_TANGENT_V | MA_NORMAP_TANG)) {
copy_v3_v3(shi->tang, spoint->tan);
copy_v3_v3(shi->nmaptang, spoint->tan);
}
if (mode & MA_STR_SURFDIFF) {
const float *surfnor = RE_strandren_get_surfnor(obr, strand, 0);
if (surfnor)
copy_v3_v3(shi->surfnor, surfnor);
else
copy_v3_v3(shi->surfnor, shi->vn);
if (shi->mat->strand_surfnor > 0.0f) {
2012-07-08 21:37:59 +00:00
shi->surfdist = 0.0f;
for (sv = strand->vert; sv != svert; sv++)
shi->surfdist += len_v3v3(sv->co, (sv + 1)->co);
shi->surfdist += spoint->t * len_v3v3(sv->co, (sv + 1)->co);
}
}
if (R.r.mode & R_SPEED) {
const float *speed;
2012-07-08 21:37:59 +00:00
speed = RE_strandren_get_winspeed(shi->obi, strand, 0);
if (speed)
copy_v4_v4(shi->winspeed, speed);
else
2012-07-08 21:37:59 +00:00
shi->winspeed[0] = shi->winspeed[1] = shi->winspeed[2] = shi->winspeed[3] = 0.0f;
}
/* shade_input_set_shade_texco equivalent */
if (texco & NEED_UV) {
if (texco & TEXCO_ORCO) {
copy_v3_v3(shi->lo, strand->orco);
/* no shi->osatex, orco derivatives are zero */
}
if (texco & TEXCO_GLOB) {
2015-04-27 23:23:04 +10:00
mul_v3_m4v3(shi->gl, R.viewinv, shi->co);
if (shi->osatex) {
2015-04-27 23:23:04 +10:00
mul_v3_mat3_m4v3(shi->dxgl, R.viewinv, shi->dxco);
mul_v3_mat3_m4v3(shi->dygl, R.viewinv, shi->dyco);
}
}
if (texco & TEXCO_STRAND) {
2012-07-08 21:37:59 +00:00
shi->strandco = spoint->strandco;
if (shi->osatex) {
2012-07-08 21:37:59 +00:00
shi->dxstrand = spoint->dtstrandco;
shi->dystrand = 0.0f;
}
}
2012-07-08 21:37:59 +00:00
if ((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE))) {
MCol *mcol;
const float *uv;
char *name;
int i;
2012-07-08 21:37:59 +00:00
shi->totuv = 0;
shi->totcol = 0;
shi->actuv = obr->actmtface;
shi->actcol = obr->actmcol;
2012-07-08 21:37:59 +00:00
if (mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) {
for (i = 0; (mcol = RE_strandren_get_mcol(obr, strand, i, &name, 0)); i++) {
ShadeInputCol *scol = &shi->col[i];
const char *cp = (char *)mcol;
shi->totcol++;
2012-07-08 21:37:59 +00:00
scol->name = name;
2012-07-08 21:37:59 +00:00
scol->col[0] = cp[3] / 255.0f;
scol->col[1] = cp[2] / 255.0f;
scol->col[2] = cp[1] / 255.0f;
scol->col[3] = cp[0] / 255.0f;
}
if (shi->totcol) {
2012-07-08 21:37:59 +00:00
shi->vcol[0] = shi->col[shi->actcol].col[0];
shi->vcol[1] = shi->col[shi->actcol].col[1];
shi->vcol[2] = shi->col[shi->actcol].col[2];
shi->vcol[3] = shi->col[shi->actcol].col[3];
}
else {
2012-07-08 21:37:59 +00:00
shi->vcol[0] = 0.0f;
shi->vcol[1] = 0.0f;
shi->vcol[2] = 0.0f;
shi->vcol[3] = 0.0f;
}
}
2012-07-08 21:37:59 +00:00
for (i = 0; (uv = RE_strandren_get_uv(obr, strand, i, &name, 0)); i++) {
ShadeInputUV *suv = &shi->uv[i];
shi->totuv++;
2012-07-08 21:37:59 +00:00
suv->name = name;
if (strandbuf->overrideuv == i) {
2012-07-08 21:37:59 +00:00
suv->uv[0] = -1.0f;
suv->uv[1] = spoint->strandco;
suv->uv[2] = 0.0f;
}
else {
2012-07-08 21:37:59 +00:00
suv->uv[0] = -1.0f + 2.0f * uv[0];
suv->uv[1] = -1.0f + 2.0f * uv[1];
suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */
}
if (shi->osatex) {
2012-07-08 21:37:59 +00:00
suv->dxuv[0] = 0.0f;
suv->dxuv[1] = 0.0f;
suv->dyuv[0] = 0.0f;
suv->dyuv[1] = 0.0f;
}
2012-07-08 21:37:59 +00:00
if ((mode & MA_FACETEXTURE) && i == obr->actmtface) {
if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) {
shi->vcol[0] = 1.0f;
shi->vcol[1] = 1.0f;
shi->vcol[2] = 1.0f;
shi->vcol[3] = 1.0f;
}
}
}
if (shi->totuv == 0) {
2012-07-08 21:37:59 +00:00
ShadeInputUV *suv = &shi->uv[0];
2012-07-08 21:37:59 +00:00
suv->uv[0] = 0.0f;
suv->uv[1] = spoint->strandco;
suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */
if (mode & MA_FACETEXTURE) {
/* no tface? set at 1.0f */
2012-07-08 21:37:59 +00:00
shi->vcol[0] = 1.0f;
shi->vcol[1] = 1.0f;
shi->vcol[2] = 1.0f;
shi->vcol[3] = 1.0f;
}
}
}
if (texco & TEXCO_NORM) {
2012-07-08 21:37:59 +00:00
shi->orn[0] = -shi->vn[0];
shi->orn[1] = -shi->vn[1];
shi->orn[2] = -shi->vn[2];
}
if (texco & TEXCO_STRESS) {
/* not supported */
}
if (texco & TEXCO_TANGENT) {
2012-07-08 21:37:59 +00:00
if ((mode & MA_TANGENT_V) == 0) {
/* just prevent surprises */
2012-07-08 21:37:59 +00:00
shi->tang[0] = shi->tang[1] = shi->tang[2] = 0.0f;
shi->nmaptang[0] = shi->nmaptang[1] = shi->nmaptang[2] = 0.0f;
}
}
}
/* this only avalailable for scanline renders */
2012-07-08 21:37:59 +00:00
if (shi->depth == 0) {
if (texco & TEXCO_WINDOW) {
2012-07-08 21:37:59 +00:00
shi->winco[0] = -1.0f + 2.0f * spoint->x / (float)R.winx;
shi->winco[1] = -1.0f + 2.0f * spoint->y / (float)R.winy;
shi->winco[2] = 0.0f;
/* not supported */
if (shi->osatex) {
2012-07-08 21:37:59 +00:00
shi->dxwin[0] = 0.0f;
shi->dywin[1] = 0.0f;
shi->dxwin[0] = 0.0f;
shi->dywin[1] = 0.0f;
}
}
}
if (shi->do_manage) {
2012-07-08 21:37:59 +00:00
if (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) {
Changes to Color Management After testing and feedback, I've decided to slightly modify the way color management works internally. While the previous method worked well for rendering, was a smaller transition and had some advantages over this new method, it was a bit more ambiguous, and was making things difficult for other areas such as compositing. This implementation now considers all color data (with only a couple of exceptions such as brush colors) to be stored in linear RGB color space, rather than sRGB as previously. This brings it in line with Nuke, which also operates this way, quite successfully. Color swatches, pickers, color ramp display are now gamma corrected to display gamma so you can see what you're doing, but the numbers themselves are considered linear. This makes understanding blending modes more clear (a 0.5 value on overlay will not change the result now) as well as making color swatches act more predictably in the compositor, however bringing over color values from applications like photoshop or gimp, that operate in a gamma space, will give identical results. This commit will convert over existing files saved by earlier 2.5 versions to work generally the same, though there may be some slight differences with things like textures. Now that we're set on changing other areas of shading, this won't be too disruptive overall. I've made a diagram explaining the pipeline here: http://mke3.net/blender/devel/2.5/25_linear_workflow_pipeline.png and some docs here: http://www.blender.org/development/release-logs/blender-250/color-management/
2009-12-02 07:56:34 +00:00
srgb_to_linearrgb_v3_v3(shi->vcol, shi->vcol);
}
}
}
/* from scanline pixel coordinates to 3d coordinates, requires set_triangle */
void shade_input_calc_viewco(ShadeInput *shi, float x, float y, float z, float view[3], float dxyview[2], float co[3], float dxco[3], float dyco[3])
{
/* returns not normalized, so is in viewplane coords */
calc_view_vector(view, x, y);
if (shi->mat->material_type == MA_TYPE_WIRE) {
/* wire cannot use normal for calculating shi->co, so
* we reconstruct the coordinate less accurate */
if (R.r.mode & R_ORTHO)
calc_renderco_ortho(co, x, y, z);
else
calc_renderco_zbuf(co, view, z);
}
else {
/* for non-wire, intersect with the triangle to get the exact coord */
float fac, dface, v1[3];
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
copy_v3_v3(v1, shi->v1->co);
if (shi->obi->flag & R_TRANSFORMED)
mul_m4_v3(shi->obi->mat, v1);
dface = dot_v3v3(v1, shi->facenor);
/* ortho viewplane cannot intersect using view vector originating in (0,0,0) */
if (R.r.mode & R_ORTHO) {
/* x and y 3d coordinate can be derived from pixel coord and winmat */
2012-07-08 21:37:59 +00:00
float fx = 2.0f / (R.winx * R.winmat[0][0]);
float fy = 2.0f / (R.winy * R.winmat[1][1]);
2012-07-08 21:37:59 +00:00
co[0] = (x - 0.5f * R.winx) * fx - R.winmat[3][0] / R.winmat[0][0];
co[1] = (y - 0.5f * R.winy) * fy - R.winmat[3][1] / R.winmat[1][1];
/* using a*x + b*y + c*z = d equation, (a b c) is normal */
2012-07-08 21:37:59 +00:00
if (shi->facenor[2] != 0.0f)
co[2] = (dface - shi->facenor[0] * co[0] - shi->facenor[1] * co[1]) / shi->facenor[2];
else
2012-07-08 21:37:59 +00:00
co[2] = 0.0f;
if (dxco && dyco) {
2012-07-08 21:37:59 +00:00
dxco[0] = fx;
dxco[1] = 0.0f;
if (shi->facenor[2] != 0.0f)
dxco[2] = -(shi->facenor[0] * fx) / shi->facenor[2];
else
2012-07-08 21:37:59 +00:00
dxco[2] = 0.0f;
2012-07-08 21:37:59 +00:00
dyco[0] = 0.0f;
dyco[1] = fy;
if (shi->facenor[2] != 0.0f)
dyco[2] = -(shi->facenor[1] * fy) / shi->facenor[2];
else
2012-07-08 21:37:59 +00:00
dyco[2] = 0.0f;
if (dxyview) {
fac = (co[2] != 0.0f) ? (1.0f / co[2]) : 0.0f;
2012-07-08 21:37:59 +00:00
dxyview[0] = -R.viewdx * fac;
dxyview[1] = -R.viewdy * fac;
}
}
}
else {
float div;
div = dot_v3v3(shi->facenor, view);
2012-07-08 21:37:59 +00:00
if (div != 0.0f) fac = dface / div;
else fac = 0.0f;
2012-07-08 21:37:59 +00:00
co[0] = fac * view[0];
co[1] = fac * view[1];
co[2] = fac * view[2];
/* pixel dx/dy for render coord */
if (dxco && dyco) {
2012-07-08 21:37:59 +00:00
float u = dface / (div - R.viewdx * shi->facenor[0]);
float v = dface / (div - R.viewdy * shi->facenor[1]);
2012-07-08 21:37:59 +00:00
dxco[0] = co[0] - (view[0] - R.viewdx) * u;
dxco[1] = co[1] - (view[1]) * u;
dxco[2] = co[2] - (view[2]) * u;
dyco[0] = co[0] - (view[0]) * v;
dyco[1] = co[1] - (view[1] - R.viewdy) * v;
dyco[2] = co[2] - (view[2]) * v;
if (dxyview) {
2012-07-08 21:37:59 +00:00
if (fac != 0.0f) fac = 1.0f / fac;
dxyview[0] = -R.viewdx * fac;
dxyview[1] = -R.viewdy * fac;
}
}
}
}
/* set camera coords - for scanline, it's always 0.0,0.0,0.0 (render is in camera space)
* however for raytrace it can be different - the position of the last intersection */
shi->camera_co[0] = shi->camera_co[1] = shi->camera_co[2] = 0.0f;
/* cannot normalize earlier, code above needs it at viewplane level */
normalize_v3(view);
}
/* from scanline pixel coordinates to 3d coordinates, requires set_triangle */
void shade_input_set_viewco(ShadeInput *shi, float x, float y, float xs, float ys, float z)
{
2012-07-08 21:37:59 +00:00
float *dxyview = NULL, *dxco = NULL, *dyco = NULL;
/* currently in use for dithering (soft shadow), node preview, irregular shad */
2012-07-08 21:37:59 +00:00
shi->xs = (int)xs;
shi->ys = (int)ys;
/* original scanline coordinate without jitter */
2012-07-08 21:37:59 +00:00
shi->scanco[0] = x;
shi->scanco[1] = y;
shi->scanco[2] = z;
/* check if we need derivatives */
if (shi->osatex || (R.r.mode & R_SHADOW)) {
2012-07-08 21:37:59 +00:00
dxco = shi->dxco;
dyco = shi->dyco;
if ((shi->mat->texco & TEXCO_REFL))
2012-07-08 21:37:59 +00:00
dxyview = &shi->dxview;
}
shade_input_calc_viewco(shi, xs, ys, z, shi->view, dxyview, shi->co, dxco, dyco);
}
void barycentric_differentials_from_position(
const float co[3], const float v1[3], const float v2[3], const float v3[3],
const float dxco[3], const float dyco[3], const float facenor[3], const bool differentials,
float *u, float *v, float *dx_u, float *dx_v, float *dy_u, float *dy_v)
{
/* find most stable axis to project */
int axis1, axis2;
axis_dominant_v3(&axis1, &axis2, facenor);
/* compute u,v and derivatives */
float t00 = v3[axis1] - v1[axis1];
float t01 = v3[axis2] - v1[axis2];
float t10 = v3[axis1] - v2[axis1];
float t11 = v3[axis2] - v2[axis2];
float detsh = (t00 * t11 - t10 * t01);
detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f;
t00 *= detsh; t01 *= detsh;
t10 *= detsh; t11 *= detsh;
*u = (v3[axis1] - co[axis1]) * t11 - (v3[axis2] - co[axis2]) * t10;
*v = (v3[axis2] - co[axis2]) * t00 - (v3[axis1] - co[axis1]) * t01;
if (differentials) {
*dx_u = dxco[axis1] * t11 - dxco[axis2] * t10;
*dx_v = dxco[axis2] * t00 - dxco[axis1] * t01;
*dy_u = dyco[axis1] * t11 - dyco[axis2] * t10;
*dy_v = dyco[axis2] * t00 - dyco[axis1] * t01;
}
}
/* calculate U and V, for scanline (silly render face u and v are in range -1 to 0) */
void shade_input_set_uv(ShadeInput *shi)
{
2012-07-08 21:37:59 +00:00
VlakRen *vlr = shi->vlr;
if ((vlr->flag & R_SMOOTH) || (shi->mat->texco & NEED_UV) || (shi->passflag & SCE_PASS_UV)) {
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
float v1[3], v2[3], v3[3];
copy_v3_v3(v1, shi->v1->co);
copy_v3_v3(v2, shi->v2->co);
copy_v3_v3(v3, shi->v3->co);
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
if (shi->obi->flag & R_TRANSFORMED) {
mul_m4_v3(shi->obi->mat, v1);
mul_m4_v3(shi->obi->mat, v2);
mul_m4_v3(shi->obi->mat, v3);
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
}
/* exception case for wire render of edge */
2012-07-08 21:37:59 +00:00
if (vlr->v2 == vlr->v3) {
float lend, lenc;
2012-07-08 21:37:59 +00:00
lend = len_v3v3(v2, v1);
lenc = len_v3v3(shi->co, v1);
2012-07-08 21:37:59 +00:00
if (lend == 0.0f) {
shi->u = shi->v = 0.0f;
}
else {
2012-07-08 21:37:59 +00:00
shi->u = -(1.0f - lenc / lend);
shi->v = 0.0f;
}
if (shi->osatex) {
2012-07-08 21:37:59 +00:00
shi->dx_u = 0.0f;
shi->dx_v = 0.0f;
shi->dy_u = 0.0f;
shi->dy_v = 0.0f;
}
}
else {
barycentric_differentials_from_position(
shi->co, v1, v2, v3, shi->dxco, shi->dyco, shi->facenor, shi->osatex,
&shi->u, &shi->v, &shi->dx_u, &shi->dx_v, &shi->dy_u, &shi->dy_v);
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
shi->u = -shi->u;
shi->v = -shi->v;
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
/* u and v are in range -1 to 0, we allow a little bit extra but not too much, screws up speedvectors */
CLAMP(shi->u, -2.0f, 1.0f);
CLAMP(shi->v, -2.0f, 1.0f);
}
}
}
void shade_input_set_normals(ShadeInput *shi)
{
2012-07-08 21:37:59 +00:00
float u = shi->u, v = shi->v;
float l = 1.0f + u + v;
shi->flippednor = 0;
/* test flip normals to viewing direction */
if (!(shi->vlr->flag & R_TANGENT)) {
if (dot_v3v3(shi->facenor, shi->view) < 0.0f) {
negate_v3(shi->facenor);
2012-07-08 21:37:59 +00:00
shi->flippednor = 1;
}
}
/* calculate vertexnormals */
if (shi->vlr->flag & R_SMOOTH) {
2012-07-08 21:37:59 +00:00
float *n1 = shi->n1, *n2 = shi->n2, *n3 = shi->n3;
if (shi->flippednor) {
negate_v3(n1);
negate_v3(n2);
negate_v3(n3);
}
2012-07-08 21:37:59 +00:00
shi->vn[0] = l * n3[0] - u * n1[0] - v * n2[0];
shi->vn[1] = l * n3[1] - u * n1[1] - v * n2[1];
shi->vn[2] = l * n3[2] - u * n1[2] - v * n2[2];
2012-07-07 22:51:57 +00:00
/* use unnormalized normal (closer to games) */
copy_v3_v3(shi->nmapnorm, shi->vn);
normalize_v3(shi->vn);
}
else {
copy_v3_v3(shi->vn, shi->facenor);
copy_v3_v3(shi->nmapnorm, shi->vn);
}
/* used in nodes */
copy_v3_v3(shi->vno, shi->vn);
/* flip normals to viewing direction */
if (!(shi->vlr->flag & R_TANGENT))
if (dot_v3v3(shi->facenor, shi->view) < 0.0f)
shade_input_flip_normals(shi);
}
/* XXX shi->flippednor messes up otherwise */
void shade_input_set_vertex_normals(ShadeInput *shi)
{
2012-07-08 21:37:59 +00:00
float u = shi->u, v = shi->v;
float l = 1.0f + u + v;
/* calculate vertexnormals */
if (shi->vlr->flag & R_SMOOTH) {
2012-07-08 21:37:59 +00:00
const float *n1 = shi->n1, *n2 = shi->n2, *n3 = shi->n3;
2012-07-08 21:37:59 +00:00
shi->vn[0] = l * n3[0] - u * n1[0] - v * n2[0];
shi->vn[1] = l * n3[1] - u * n1[1] - v * n2[1];
shi->vn[2] = l * n3[2] - u * n1[2] - v * n2[2];
2012-07-07 22:51:57 +00:00
/* use unnormalized normal (closer to games) */
copy_v3_v3(shi->nmapnorm, shi->vn);
normalize_v3(shi->vn);
}
else {
copy_v3_v3(shi->vn, shi->facenor);
copy_v3_v3(shi->nmapnorm, shi->vn);
}
/* used in nodes */
copy_v3_v3(shi->vno, shi->vn);
}
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
/* use by raytrace, sss, bake to flip into the right direction */
void shade_input_flip_normals(ShadeInput *shi)
{
2012-07-08 21:37:59 +00:00
negate_v3(shi->facenor);
negate_v3(shi->vn);
negate_v3(shi->vno);
negate_v3(shi->nmapnorm);
shi->flippednor = !shi->flippednor;
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
}
void shade_input_set_shade_texco(ShadeInput *shi)
{
2012-07-08 21:37:59 +00:00
ObjectInstanceRen *obi = shi->obi;
ObjectRen *obr = shi->obr;
VertRen *v1 = shi->v1, *v2 = shi->v2, *v3 = shi->v3;
float u = shi->u, v = shi->v;
float l = 1.0f + u + v, dl;
int mode = shi->mode; /* or-ed result for all nodes */
int mode2 = shi->mode2;
2012-07-08 21:37:59 +00:00
short texco = shi->mat->texco;
const bool need_mikk_tangent = (mode & MA_NORMAP_TANG || R.flag & R_NEED_TANGENT);
const bool need_mikk_tangent_concrete = (mode2 & MA_TANGENT_CONCRETE) != 0;
/* calculate dxno */
if (shi->vlr->flag & R_SMOOTH) {
2012-07-08 21:37:59 +00:00
if (shi->osatex && (texco & (TEXCO_NORM | TEXCO_REFL)) ) {
const float *n1 = shi->n1, *n2 = shi->n2, *n3 = shi->n3;
2012-07-08 21:37:59 +00:00
dl = shi->dx_u + shi->dx_v;
shi->dxno[0] = dl * n3[0] - shi->dx_u * n1[0] - shi->dx_v * n2[0];
shi->dxno[1] = dl * n3[1] - shi->dx_u * n1[1] - shi->dx_v * n2[1];
shi->dxno[2] = dl * n3[2] - shi->dx_u * n1[2] - shi->dx_v * n2[2];
dl = shi->dy_u + shi->dy_v;
shi->dyno[0] = dl * n3[0] - shi->dy_u * n1[0] - shi->dy_v * n2[0];
shi->dyno[1] = dl * n3[1] - shi->dy_u * n1[1] - shi->dy_v * n2[1];
shi->dyno[2] = dl * n3[2] - shi->dy_u * n1[2] - shi->dy_v * n2[2];
}
}
/* calc tangents */
if (mode & (MA_TANGENT_V | MA_NORMAP_TANG) || mode2 & MA_TANGENT_CONCRETE || R.flag & R_NEED_TANGENT) {
const float *s1, *s2, *s3;
float tl, tu, tv;
if (shi->vlr->flag & R_SMOOTH) {
2012-07-08 21:37:59 +00:00
tl = l;
tu = u;
tv = v;
}
else {
/* qdn: flat faces have tangents too,
2012-03-09 18:28:30 +00:00
* could pick either one, using average here */
2012-07-08 21:37:59 +00:00
tl = 1.0f / 3.0f;
tu = -1.0f / 3.0f;
tv = -1.0f / 3.0f;
}
2012-07-08 21:37:59 +00:00
shi->tang[0] = shi->tang[1] = shi->tang[2] = 0.0f;
shi->nmaptang[0] = shi->nmaptang[1] = shi->nmaptang[2] = 0.0f;
if (mode & MA_TANGENT_V) {
s1 = RE_vertren_get_tangent(obr, v1, 0);
s2 = RE_vertren_get_tangent(obr, v2, 0);
s3 = RE_vertren_get_tangent(obr, v3, 0);
if (s1 && s2 && s3) {
2012-07-08 21:37:59 +00:00
shi->tang[0] = (tl * s3[0] - tu * s1[0] - tv * s2[0]);
shi->tang[1] = (tl * s3[1] - tu * s1[1] - tv * s2[1]);
shi->tang[2] = (tl * s3[2] - tu * s1[2] - tv * s2[2]);
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
if (obi->flag & R_TRANSFORMED)
mul_m3_v3(obi->nmat, shi->tang);
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
normalize_v3(shi->tang);
copy_v3_v3(shi->nmaptang, shi->tang);
}
}
if (need_mikk_tangent || need_mikk_tangent_concrete) {
int j1 = shi->i1, j2 = shi->i2, j3 = shi->i3;
float c0[3], c1[3], c2[3];
int acttang = obr->actmtface;
vlr_set_uv_indices(shi->vlr, &j1, &j2, &j3);
/* cycle through all tangent in vlakren */
for (int i = 0; i < MAX_MTFACE; i++) {
const float *tangent = RE_vlakren_get_nmap_tangent(obr, shi->vlr, i, false);
if (!tangent)
continue;
2012-07-08 21:37:59 +00:00
copy_v3_v3(c0, &tangent[j1 * 4]);
copy_v3_v3(c1, &tangent[j2 * 4]);
copy_v3_v3(c2, &tangent[j3 * 4]);
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
2012-07-07 22:51:57 +00:00
/* keeping tangents normalized at vertex level
* corresponds better to how it's done in game engines */
if (obi->flag & R_TRANSFORMED) {
mul_mat3_m4_v3(obi->mat, c0); normalize_v3(c0);
mul_mat3_m4_v3(obi->mat, c1); normalize_v3(c1);
mul_mat3_m4_v3(obi->mat, c2); normalize_v3(c2);
}
2012-07-07 22:51:57 +00:00
/* we don't normalize the interpolated TBN tangent
* corresponds better to how it's done in game engines */
shi->tangents[i][0] = (tl * c2[0] - tu * c0[0] - tv * c1[0]);
shi->tangents[i][1] = (tl * c2[1] - tu * c0[1] - tv * c1[1]);
shi->tangents[i][2] = (tl * c2[2] - tu * c0[2] - tv * c1[2]);
2012-07-07 22:51:57 +00:00
/* the sign is the same for all 3 vertices of any
* non degenerate triangle. */
shi->tangents[i][3] = tangent[j1 * 4 + 3];
if (acttang == i && need_mikk_tangent) {
for (int m = 0; m < 4; m++) {
shi->nmaptang[m] = shi->tangents[i][m];
}
}
}
}
}
if (mode & MA_STR_SURFDIFF) {
const float *surfnor = RE_vlakren_get_surfnor(obr, shi->vlr, 0);
if (surfnor) {
copy_v3_v3(shi->surfnor, surfnor);
if (obi->flag & R_TRANSFORMED)
mul_m3_v3(obi->nmat, shi->surfnor);
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
}
else
copy_v3_v3(shi->surfnor, shi->vn);
2012-07-08 21:37:59 +00:00
shi->surfdist = 0.0f;
}
if (R.r.mode & R_SPEED) {
const float *s1, *s2, *s3;
2012-07-08 21:37:59 +00:00
s1 = RE_vertren_get_winspeed(obi, v1, 0);
s2 = RE_vertren_get_winspeed(obi, v2, 0);
s3 = RE_vertren_get_winspeed(obi, v3, 0);
if (s1 && s2 && s3) {
2012-07-08 21:37:59 +00:00
shi->winspeed[0] = (l * s3[0] - u * s1[0] - v * s2[0]);
shi->winspeed[1] = (l * s3[1] - u * s1[1] - v * s2[1]);
shi->winspeed[2] = (l * s3[2] - u * s1[2] - v * s2[2]);
shi->winspeed[3] = (l * s3[3] - u * s1[3] - v * s2[3]);
}
else {
2012-07-08 21:37:59 +00:00
shi->winspeed[0] = shi->winspeed[1] = shi->winspeed[2] = shi->winspeed[3] = 0.0f;
}
}
/* pass option forces UV calc */
if ((shi->passflag & SCE_PASS_UV) || (R.flag & R_NEED_VCOL))
2012-07-08 21:37:59 +00:00
texco |= (NEED_UV | TEXCO_UV);
/* texture coordinates. shi->dxuv shi->dyuv have been set */
if (texco & NEED_UV) {
if (texco & TEXCO_ORCO) {
if (v1->orco) {
const float *o1, *o2, *o3;
2012-07-08 21:37:59 +00:00
o1 = v1->orco;
o2 = v2->orco;
o3 = v3->orco;
shi->lo[0] = l * o3[0] - u * o1[0] - v * o2[0];
shi->lo[1] = l * o3[1] - u * o1[1] - v * o2[1];
shi->lo[2] = l * o3[2] - u * o1[2] - v * o2[2];
if (shi->osatex) {
2012-07-08 21:37:59 +00:00
dl = shi->dx_u + shi->dx_v;
shi->dxlo[0] = dl * o3[0] - shi->dx_u * o1[0] - shi->dx_v * o2[0];
shi->dxlo[1] = dl * o3[1] - shi->dx_u * o1[1] - shi->dx_v * o2[1];
shi->dxlo[2] = dl * o3[2] - shi->dx_u * o1[2] - shi->dx_v * o2[2];
dl = shi->dy_u + shi->dy_v;
shi->dylo[0] = dl * o3[0] - shi->dy_u * o1[0] - shi->dy_v * o2[0];
shi->dylo[1] = dl * o3[1] - shi->dy_u * o1[1] - shi->dy_v * o2[1];
shi->dylo[2] = dl * o3[2] - shi->dy_u * o1[2] - shi->dy_v * o2[2];
}
}
copy_v3_v3(shi->duplilo, obi->dupliorco);
}
if (texco & TEXCO_GLOB) {
copy_v3_v3(shi->gl, shi->co);
mul_m4_v3(R.viewinv, shi->gl);
if (shi->osatex) {
copy_v3_v3(shi->dxgl, shi->dxco);
mul_mat3_m4_v3(R.viewinv, shi->dxgl);
copy_v3_v3(shi->dygl, shi->dyco);
mul_mat3_m4_v3(R.viewinv, shi->dygl);
}
}
if (texco & TEXCO_STRAND) {
2012-07-08 21:37:59 +00:00
shi->strandco = (l * v3->accum - u * v1->accum - v * v2->accum);
if (shi->osatex) {
2012-07-08 21:37:59 +00:00
dl = shi->dx_u + shi->dx_v;
shi->dxstrand = dl * v3->accum - shi->dx_u * v1->accum - shi->dx_v * v2->accum;
dl = shi->dy_u + shi->dy_v;
shi->dystrand = dl * v3->accum - shi->dy_u * v1->accum - shi->dy_v * v2->accum;
}
}
if ((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) || (R.flag & R_NEED_VCOL)) {
2012-07-08 21:37:59 +00:00
VlakRen *vlr = shi->vlr;
MTFace *tface;
MCol *mcol;
char *name;
2012-07-08 21:37:59 +00:00
int i, j1 = shi->i1, j2 = shi->i2, j3 = shi->i3;
/* uv and vcols are not copied on split, so set them according vlr divide flag */
vlr_set_uv_indices(vlr, &j1, &j2, &j3);
2012-07-08 21:37:59 +00:00
shi->totuv = 0;
shi->totcol = 0;
shi->actuv = obr->actmtface;
shi->actcol = obr->actmcol;
if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) || (R.flag & R_NEED_VCOL)) {
2012-07-08 21:37:59 +00:00
for (i = 0; (mcol = RE_vlakren_get_mcol(obr, vlr, i, &name, 0)); i++) {
ShadeInputCol *scol = &shi->col[i];
const char *cp1, *cp2, *cp3;
float a[3];
shi->totcol++;
2012-07-08 21:37:59 +00:00
scol->name = name;
2012-07-08 21:37:59 +00:00
cp1 = (char *)(mcol + j1);
cp2 = (char *)(mcol + j2);
cp3 = (char *)(mcol + j3);
/* alpha values */
2012-07-08 21:37:59 +00:00
a[0] = ((float)cp1[0]) / 255.f;
a[1] = ((float)cp2[0]) / 255.f;
a[2] = ((float)cp3[0]) / 255.f;
scol->col[3] = l * a[2] - u * a[0] - v * a[1];
/* sample premultiplied color value */
2012-07-08 21:37:59 +00:00
scol->col[0] = (l * ((float)cp3[3]) * a[2] - u * ((float)cp1[3]) * a[0] - v * ((float)cp2[3]) * a[1]) / 255.f;
scol->col[1] = (l * ((float)cp3[2]) * a[2] - u * ((float)cp1[2]) * a[0] - v * ((float)cp2[2]) * a[1]) / 255.f;
scol->col[2] = (l * ((float)cp3[1]) * a[2] - u * ((float)cp1[1]) * a[0] - v * ((float)cp2[1]) * a[1]) / 255.f;
/* if not zero alpha, restore non-multiplied color */
if (scol->col[3]) {
2012-07-08 21:37:59 +00:00
mul_v3_fl(scol->col, 1.0f / scol->col[3]);
}
}
if (shi->totcol) {
2012-07-08 21:37:59 +00:00
shi->vcol[0] = shi->col[shi->actcol].col[0];
shi->vcol[1] = shi->col[shi->actcol].col[1];
shi->vcol[2] = shi->col[shi->actcol].col[2];
shi->vcol[3] = shi->col[shi->actcol].col[3];
}
else {
2012-07-08 21:37:59 +00:00
shi->vcol[0] = 0.0f;
shi->vcol[1] = 0.0f;
shi->vcol[2] = 0.0f;
shi->vcol[3] = 1.0f;
}
}
2012-07-08 21:37:59 +00:00
for (i = 0; (tface = RE_vlakren_get_tface(obr, vlr, i, &name, 0)); i++) {
ShadeInputUV *suv = &shi->uv[i];
const float *uv1 = tface->uv[j1];
const float *uv2 = tface->uv[j2];
const float *uv3 = tface->uv[j3];
shi->totuv++;
2012-07-08 21:37:59 +00:00
suv->name = name;
if ((shi->mat->mapflag & MA_MAPFLAG_UVPROJECT) && (shi->depth == 0)) {
float x = shi->xs;
float y = shi->ys;
float s1[2] = {-1.0f + 2.0f * uv1[0], -1.0f + 2.0f * uv1[1]};
float s2[2] = {-1.0f + 2.0f * uv2[0], -1.0f + 2.0f * uv2[1]};
float s3[2] = {-1.0f + 2.0f * uv3[0], -1.0f + 2.0f * uv3[1]};
float obwinmat[4][4], winmat[4][4], ho1[4], ho2[4], ho3[4];
float Zmulx, Zmuly;
2015-11-23 12:28:01 +11:00
float hox, hoy, l_proj, dl_proj, u_proj, v_proj;
float s00, s01, s10, s11, detsh;
/* old globals, localized now */
Zmulx = ((float)R.winx) / 2.0f;
Zmuly = ((float)R.winy) / 2.0f;
zbuf_make_winmat(&R, winmat);
if (shi->obi->flag & R_TRANSFORMED)
mul_m4_m4m4(obwinmat, winmat, obi->mat);
else
copy_m4_m4(obwinmat, winmat);
zbuf_render_project(obwinmat, v1->co, ho1);
zbuf_render_project(obwinmat, v2->co, ho2);
zbuf_render_project(obwinmat, v3->co, ho3);
s00 = ho3[0] / ho3[3] - ho1[0] / ho1[3];
s01 = ho3[1] / ho3[3] - ho1[1] / ho1[3];
s10 = ho3[0] / ho3[3] - ho2[0] / ho2[3];
s11 = ho3[1] / ho3[3] - ho2[1] / ho2[3];
detsh = s00 * s11 - s10 * s01;
detsh = (detsh != 0.0f) ? 1.0f / detsh : 0.0f;
s00 *= detsh; s01 *= detsh;
s10 *= detsh; s11 *= detsh;
/* recalc u and v again */
hox = x / Zmulx - 1.0f;
hoy = y / Zmuly - 1.0f;
2015-11-23 12:28:01 +11:00
u_proj = (hox - ho3[0] / ho3[3]) * s11 - (hoy - ho3[1] / ho3[3]) * s10;
v_proj = (hoy - ho3[1] / ho3[3]) * s00 - (hox - ho3[0] / ho3[3]) * s01;
l_proj = 1.0f + u_proj + v_proj;
2015-11-23 12:28:01 +11:00
suv->uv[0] = l_proj * s3[0] - u_proj * s1[0] - v_proj * s2[0];
suv->uv[1] = l_proj * s3[1] - u_proj * s1[1] - v_proj * s2[1];
suv->uv[2] = 0.0f;
if (shi->osatex) {
float dxuv[2], dyuv[2];
dxuv[0] = s11 / Zmulx;
dxuv[1] = -s01 / Zmulx;
dyuv[0] = -s10 / Zmuly;
dyuv[1] = s00 / Zmuly;
2015-11-23 12:28:01 +11:00
dl_proj = dxuv[0] + dxuv[1];
suv->dxuv[0] = dl_proj * s3[0] - dxuv[0] * s1[0] - dxuv[1] * s2[0];
suv->dxuv[1] = dl_proj * s3[1] - dxuv[0] * s1[1] - dxuv[1] * s2[1];
dl_proj = dyuv[0] + dyuv[1];
suv->dyuv[0] = dl_proj * s3[0] - dyuv[0] * s1[0] - dyuv[1] * s2[0];
suv->dyuv[1] = dl_proj * s3[1] - dyuv[0] * s1[1] - dyuv[1] * s2[1];
}
}
else {
2012-07-08 21:37:59 +00:00
suv->uv[0] = -1.0f + 2.0f * (l * uv3[0] - u * uv1[0] - v * uv2[0]);
suv->uv[1] = -1.0f + 2.0f * (l * uv3[1] - u * uv1[1] - v * uv2[1]);
suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */
2012-07-08 21:37:59 +00:00
if (shi->osatex) {
float duv[2];
2012-07-08 21:37:59 +00:00
dl = shi->dx_u + shi->dx_v;
duv[0] = shi->dx_u;
duv[1] = shi->dx_v;
suv->dxuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]);
suv->dxuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]);
dl = shi->dy_u + shi->dy_v;
duv[0] = shi->dy_u;
duv[1] = shi->dy_v;
suv->dyuv[0] = 2.0f * (dl * uv3[0] - duv[0] * uv1[0] - duv[1] * uv2[0]);
suv->dyuv[1] = 2.0f * (dl * uv3[1] - duv[0] * uv1[1] - duv[1] * uv2[1]);
}
if ((mode & MA_FACETEXTURE) && i == obr->actmtface) {
if (((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) && ((R.flag & R_NEED_VCOL) == 0)) {
shi->vcol[0] = 1.0f;
shi->vcol[1] = 1.0f;
shi->vcol[2] = 1.0f;
shi->vcol[3] = 1.0f;
}
if (tface->tpage) {
render_realtime_texture(shi, tface->tpage);
}
}
}
}
2012-07-08 21:37:59 +00:00
shi->dupliuv[0] = -1.0f + 2.0f * obi->dupliuv[0];
shi->dupliuv[1] = -1.0f + 2.0f * obi->dupliuv[1];
shi->dupliuv[2] = 0.0f;
if (shi->totuv == 0) {
2012-07-08 21:37:59 +00:00
ShadeInputUV *suv = &shi->uv[0];
2012-07-08 21:37:59 +00:00
suv->uv[0] = 2.0f * (u + .5f);
suv->uv[1] = 2.0f * (v + .5f);
suv->uv[2] = 0.0f; /* texture.c assumes there are 3 coords */
if (mode & MA_FACETEXTURE) {
/* no tface? set at 1.0f */
2012-07-08 21:37:59 +00:00
shi->vcol[0] = 1.0f;
shi->vcol[1] = 1.0f;
shi->vcol[2] = 1.0f;
shi->vcol[3] = 1.0f;
}
}
}
if (texco & TEXCO_NORM) {
2012-07-08 21:37:59 +00:00
shi->orn[0] = -shi->vn[0];
shi->orn[1] = -shi->vn[1];
shi->orn[2] = -shi->vn[2];
}
if (texco & TEXCO_STRESS) {
const float *s1, *s2, *s3;
2012-07-08 21:37:59 +00:00
s1 = RE_vertren_get_stress(obr, v1, 0);
s2 = RE_vertren_get_stress(obr, v2, 0);
s3 = RE_vertren_get_stress(obr, v3, 0);
if (s1 && s2 && s3) {
2012-07-08 21:37:59 +00:00
shi->stress = l * s3[0] - u * s1[0] - v * s2[0];
if (shi->stress < 1.0f) shi->stress -= 1.0f;
else shi->stress = (shi->stress - 1.0f) / shi->stress;
}
2012-07-08 21:37:59 +00:00
else shi->stress = 0.0f;
}
if (texco & TEXCO_TANGENT) {
2012-07-08 21:37:59 +00:00
if ((mode & MA_TANGENT_V) == 0) {
/* just prevent surprises */
2012-07-08 21:37:59 +00:00
shi->tang[0] = shi->tang[1] = shi->tang[2] = 0.0f;
shi->nmaptang[0] = shi->nmaptang[1] = shi->nmaptang[2] = 0.0f;
}
}
}
/* this only avalailable for scanline renders */
2012-07-08 21:37:59 +00:00
if (shi->depth == 0) {
float x = shi->xs;
float y = shi->ys;
if (texco & TEXCO_WINDOW) {
2012-07-08 21:37:59 +00:00
shi->winco[0] = -1.0f + 2.0f * x / (float)R.winx;
shi->winco[1] = -1.0f + 2.0f * y / (float)R.winy;
shi->winco[2] = 0.0f;
if (shi->osatex) {
2012-07-08 21:37:59 +00:00
shi->dxwin[0] = 2.0f / (float)R.winx;
shi->dywin[1] = 2.0f / (float)R.winy;
shi->dxwin[1] = shi->dxwin[2] = 0.0f;
shi->dywin[0] = shi->dywin[2] = 0.0f;
}
}
2012-03-09 18:28:30 +00:00
}
/* else {
* Note! For raytracing winco is not set,
* important because thus means all shader input's need to have their variables set to zero
* else un-initialized values are used
*/
if (shi->do_manage) {
if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) || (R.flag & R_NEED_VCOL)) {
Changes to Color Management After testing and feedback, I've decided to slightly modify the way color management works internally. While the previous method worked well for rendering, was a smaller transition and had some advantages over this new method, it was a bit more ambiguous, and was making things difficult for other areas such as compositing. This implementation now considers all color data (with only a couple of exceptions such as brush colors) to be stored in linear RGB color space, rather than sRGB as previously. This brings it in line with Nuke, which also operates this way, quite successfully. Color swatches, pickers, color ramp display are now gamma corrected to display gamma so you can see what you're doing, but the numbers themselves are considered linear. This makes understanding blending modes more clear (a 0.5 value on overlay will not change the result now) as well as making color swatches act more predictably in the compositor, however bringing over color values from applications like photoshop or gimp, that operate in a gamma space, will give identical results. This commit will convert over existing files saved by earlier 2.5 versions to work generally the same, though there may be some slight differences with things like textures. Now that we're set on changing other areas of shading, this won't be too disruptive overall. I've made a diagram explaining the pipeline here: http://mke3.net/blender/devel/2.5/25_linear_workflow_pipeline.png and some docs here: http://www.blender.org/development/release-logs/blender-250/color-management/
2009-12-02 07:56:34 +00:00
srgb_to_linearrgb_v3_v3(shi->vcol, shi->vcol);
}
}
}
/* ****************** ShadeSample ************************************** */
/* initialize per part, not per pixel! */
void shade_input_initialize(ShadeInput *shi, RenderPart *pa, RenderLayer *rl, int sample)
{
memset(shi, 0, sizeof(ShadeInput));
2012-07-08 21:37:59 +00:00
shi->sample = sample;
shi->thread = pa->thread;
shi->do_preview = (R.r.scemode & R_MATNODE_PREVIEW) != 0;
Color Management, Stage 2: Switch color pipeline to use OpenColorIO Replace old color pipeline which was supporting linear/sRGB color spaces only with OpenColorIO-based pipeline. This introduces two configurable color spaces: - Input color space for images and movie clips. This space is used to convert images/movies from color space in which file is saved to Blender's linear space (for float images, byte images are not internally converted, only input space is stored for such images and used later). This setting could be found in image/clip data block settings. - Display color space which defines space in which particular display is working. This settings could be found in scene's Color Management panel. When render result is being displayed on the screen, apart from converting image to display space, some additional conversions could happen. This conversions are: - View, which defines tone curve applying before display transformation. These are different ways to view the image on the same display device. For example it could be used to emulate film view on sRGB display. - Exposure affects on image exposure before tone map is applied. - Gamma is post-display gamma correction, could be used to match particular display gamma. - RGB curves are user-defined curves which are applying before display transformation, could be used for different purposes. All this settings by default are only applying on render result and does not affect on other images. If some particular image needs to be affected by this transformation, "View as Render" setting of image data block should be set to truth. Movie clips are always affected by all display transformations. This commit also introduces configurable color space in which sequencer is working. This setting could be found in scene's Color Management panel and it should be used if such stuff as grading needs to be done in color space different from sRGB (i.e. when Film view on sRGB display is use, using VD16 space as sequencer's internal space would make grading working in space which is close to the space using for display). Some technical notes: - Image buffer's float buffer is now always in linear space, even if it was created from 16bit byte images. - Space of byte buffer is stored in image buffer's rect_colorspace property. - Profile of image buffer was removed since it's not longer meaningful. - OpenGL and GLSL is supposed to always work in sRGB space. It is possible to support other spaces, but it's quite large project which isn't so much important. - Legacy Color Management option disabled is emulated by using None display. It could have some regressions, but there's no clear way to avoid them. - If OpenColorIO is disabled on build time, it should make blender behaving in the same way as previous release with color management enabled. More details could be found at this page (more details would be added soon): http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management -- Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO integration and to Brecht van Lommel for some further development and code/ usecase review!
2012-09-15 10:05:07 +00:00
shi->do_manage = BKE_scene_check_color_management_enabled(R.scene);
shi->use_world_space_shading = BKE_scene_use_world_space_shading(R.scene);
Color Management, Stage 2: Switch color pipeline to use OpenColorIO Replace old color pipeline which was supporting linear/sRGB color spaces only with OpenColorIO-based pipeline. This introduces two configurable color spaces: - Input color space for images and movie clips. This space is used to convert images/movies from color space in which file is saved to Blender's linear space (for float images, byte images are not internally converted, only input space is stored for such images and used later). This setting could be found in image/clip data block settings. - Display color space which defines space in which particular display is working. This settings could be found in scene's Color Management panel. When render result is being displayed on the screen, apart from converting image to display space, some additional conversions could happen. This conversions are: - View, which defines tone curve applying before display transformation. These are different ways to view the image on the same display device. For example it could be used to emulate film view on sRGB display. - Exposure affects on image exposure before tone map is applied. - Gamma is post-display gamma correction, could be used to match particular display gamma. - RGB curves are user-defined curves which are applying before display transformation, could be used for different purposes. All this settings by default are only applying on render result and does not affect on other images. If some particular image needs to be affected by this transformation, "View as Render" setting of image data block should be set to truth. Movie clips are always affected by all display transformations. This commit also introduces configurable color space in which sequencer is working. This setting could be found in scene's Color Management panel and it should be used if such stuff as grading needs to be done in color space different from sRGB (i.e. when Film view on sRGB display is use, using VD16 space as sequencer's internal space would make grading working in space which is close to the space using for display). Some technical notes: - Image buffer's float buffer is now always in linear space, even if it was created from 16bit byte images. - Space of byte buffer is stored in image buffer's rect_colorspace property. - Profile of image buffer was removed since it's not longer meaningful. - OpenGL and GLSL is supposed to always work in sRGB space. It is possible to support other spaces, but it's quite large project which isn't so much important. - Legacy Color Management option disabled is emulated by using None display. It could have some regressions, but there's no clear way to avoid them. - If OpenColorIO is disabled on build time, it should make blender behaving in the same way as previous release with color management enabled. More details could be found at this page (more details would be added soon): http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management -- Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO integration and to Brecht van Lommel for some further development and code/ usecase review!
2012-09-15 10:05:07 +00:00
2012-07-08 21:37:59 +00:00
shi->lay = rl->lay;
shi->layflag = rl->layflag;
shi->passflag = rl->passflag;
shi->combinedflag = ~rl->pass_xor;
shi->mat_override = rl->mat_override;
shi->light_override = rl->light_override;
// shi->rl= rl;
/* note shi.depth==0 means first hit, not raytracing */
}
/* initialize per part, not per pixel! */
void shade_sample_initialize(ShadeSample *ssamp, RenderPart *pa, RenderLayer *rl)
{
int a, tot;
2012-07-08 21:37:59 +00:00
tot = R.osa == 0 ? 1 : R.osa;
2012-07-08 21:37:59 +00:00
for (a = 0; a < tot; a++) {
shade_input_initialize(&ssamp->shi[a], pa, rl, a);
memset(&ssamp->shr[a], 0, sizeof(ShadeResult));
}
get_sample_layers(pa, rl, ssamp->rlpp);
}
/* Do AO or (future) GI */
void shade_samples_do_AO(ShadeSample *ssamp)
{
if (!(R.r.mode & R_SHADOW))
return;
if (!(R.r.mode & R_RAYTRACE) && !(R.wrld.ao_gather_method == WO_AOGATHER_APPROX))
return;
2012-07-08 21:37:59 +00:00
if (R.wrld.mode & (WO_AMB_OCC | WO_ENV_LIGHT | WO_INDIRECT_LIGHT)) {
ShadeInput *shi = &ssamp->shi[0];
int sample;
2012-07-08 21:37:59 +00:00
if (((shi->passflag & SCE_PASS_COMBINED) && (shi->combinedflag & (SCE_PASS_AO | SCE_PASS_ENVIRONMENT | SCE_PASS_INDIRECT))) ||
(shi->passflag & (SCE_PASS_AO | SCE_PASS_ENVIRONMENT | SCE_PASS_INDIRECT)))
{
2012-07-08 21:37:59 +00:00
for (sample = 0; sample < ssamp->tot; shi++, sample++)
if (!(shi->mode & MA_SHLESS))
2012-07-08 21:37:59 +00:00
ambient_occlusion(shi); /* stores in shi->ao[] */
}
}
}
void shade_samples_fill_with_ps(ShadeSample *ssamp, PixStr *ps, int x, int y)
{
ShadeInput *shi;
float xs, ys;
2012-07-08 21:37:59 +00:00
ssamp->tot = 0;
2012-07-08 21:37:59 +00:00
for (shi = ssamp->shi; ps; ps = ps->next) {
Render Instancing ================= Big commit, but little user visible changes. - Dupliverts and duplifaces are now rendered as instances, instead of storing all of the geometry for each dupli, now an instance is created with a matrix transform refering to the source object. This should allow us to render tree leaves more memory efficient. - Radiosity and to some degree raytracing of such objects is not really efficient still. For radiosity this is fundamentally hard to solve, but raytracing an octree could be created for each object, but the current octree code with it's fixed size doesn't allow this efficiently. - The regression tests survived, but with I expect that some bugs will pop up .. hopefully not too many :). Implementation Notes ==================== - Dupligroups and linked meshes are not rendered as instances yet, since they can in fact be different due to various reasons, instancing of these types of duplis that are the same can be added for them at a later point. - Each ObjectRen now stores it's own database, instead of there being one big databases of faces, verts, .. . Which objects that are actually rendered are defined by the list of ObjectRenInstances, which all refer to an ObjectRen. - Homogeneous coordinatess and clipping is now not stored in vertices anymore, but instead computed on the fly. This couldn't work for instances. That does mean some extra computation has to be done, but memory lookups can be slow too, and this saves some memory. Overall I didn't find a significant speed impact. - OSA rendering for solid and ztransp now is different. Instead of e.g. going 8 times over the databases times and rendering the z-buffer, it now goes over the database once and renders each polygon 8 times. That was necessary to keep instances efficient, and can also give some performance improvement without instances. - There was already instancing support in the yafray export code, now it uses Blender's render instances for export. - UV and color layer storage in the render was a bit messy before, now should be easier to understand. - convertblender.c was reorganized somewhat. Regular render, speedvector and baking now use a single function to create the database, previously there was code duplicated for it. - Some of these changes were done with future multithreading of scene and shadow buffer creation in mind, though especially for scene creation much work remains to be done to make it threadsafe, since it also involves a lot of code from blenkernel, and there is an ugly conflict with the way dupli groups work here .. though in the render code itself it's almost there.
2007-12-15 20:41:45 +00:00
shade_input_set_triangle(shi, ps->obi, ps->facenr, 1);
2012-07-08 21:37:59 +00:00
if (shi->vlr) { /* NULL happens for env material or for 'all z' */
unsigned short curmask = ps->mask;
/* full osa is only set for OSA renders */
if (shi->vlr->flag & R_FULL_OSA) {
2012-07-08 21:37:59 +00:00
short shi_cp = 0, samp;
2012-07-08 21:37:59 +00:00
for (samp = 0; samp < R.osa; samp++) {
if (curmask & (1 << samp)) {
/* zbuffer has this inverse corrected, ensures xs,ys are inside pixel */
2012-07-08 21:37:59 +00:00
xs = (float)x + R.jit[samp][0] + 0.5f;
ys = (float)y + R.jit[samp][1] + 0.5f;
if (shi_cp)
2012-07-08 21:37:59 +00:00
shade_input_copy_triangle(shi, shi - 1);
2012-07-08 21:37:59 +00:00
shi->mask = (1 << samp);
// shi->rl= ssamp->rlpp[samp];
2012-07-08 21:37:59 +00:00
shi->samplenr = R.shadowsamplenr[shi->thread]++; /* this counter is not being reset per pixel */
shade_input_set_viewco(shi, x, y, xs, ys, (float)ps->z);
shade_input_set_uv(shi);
2012-07-08 21:37:59 +00:00
if (shi_cp == 0)
shade_input_set_normals(shi);
else /* XXX shi->flippednor messes up otherwise */
shade_input_set_vertex_normals(shi);
2012-07-08 21:37:59 +00:00
shi_cp = 1;
shi++;
}
}
}
else {
if (R.osa) {
2012-07-08 21:37:59 +00:00
short b = R.samples->centmask[curmask];
xs = (float)x + R.samples->centLut[b & 15] + 0.5f;
ys = (float)y + R.samples->centLut[b >> 4] + 0.5f;
}
else if (R.i.curblur) {
xs= (float)x + R.mblur_jit[R.i.curblur-1][0] + 0.5f;
ys= (float)y + R.mblur_jit[R.i.curblur-1][1] + 0.5f;
}
else {
2012-07-08 21:37:59 +00:00
xs = (float)x + 0.5f;
ys = (float)y + 0.5f;
}
2012-07-08 21:37:59 +00:00
shi->mask = curmask;
shi->samplenr = R.shadowsamplenr[shi->thread]++;
shade_input_set_viewco(shi, x, y, xs, ys, (float)ps->z);
shade_input_set_uv(shi);
shade_input_set_normals(shi);
shi++;
}
/* total sample amount, shi->sample is static set in initialize */
2012-07-08 21:37:59 +00:00
if (shi != ssamp->shi)
ssamp->tot = (shi - 1)->sample + 1;
}
}
}
/* shades samples, returns true if anything happened */
int shade_samples(ShadeSample *ssamp, PixStr *ps, int x, int y)
{
shade_samples_fill_with_ps(ssamp, ps, x, y);
if (ssamp->tot) {
2012-07-08 21:37:59 +00:00
ShadeInput *shi = ssamp->shi;
ShadeResult *shr = ssamp->shr;
int samp;
/* if shadow or AO? */
shade_samples_do_AO(ssamp);
/* if shade (all shadepinputs have same passflag) */
2012-07-08 21:37:59 +00:00
if (ssamp->shi[0].passflag & ~(SCE_PASS_Z | SCE_PASS_INDEXOB | SCE_PASS_INDEXMA)) {
2012-07-08 21:37:59 +00:00
for (samp = 0; samp < ssamp->tot; samp++, shi++, shr++) {
shade_input_set_shade_texco(shi);
shade_input_do_shade(shi, shr);
}
}
else if (shi->passflag & SCE_PASS_Z) {
2012-07-08 21:37:59 +00:00
for (samp = 0; samp < ssamp->tot; samp++, shi++, shr++)
shr->z = -shi->co[2];
}
return 1;
}
return 0;
}