Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2004-04-06 01:04:13 +0400
committerTon Roosendaal <ton@blender.org>2004-04-06 01:04:13 +0400
commit2a90de034826cd172117e6dd9764bfb481c1b14f (patch)
treea33d07ed7346bc7f7266857195a48efc0ddb957f
parente4ce73c99eca48d7d494f5e2d0ca0e034f7d4a62 (diff)
Eeshlo AO patch, revised
- Ambient Occlusion is a more sophisticated ambient trick, which takes nearby faces into account by firing a hemisphere of shadow-rays around. AKA 'dirt shader'. - Eeshlo made it a Lamp type, which doesn't fit well. I've moved the settings to the World menu, and let the Material->ambient value control the amount it contributes - currently, the AO value is added/subtracted/mixed with the 'diffuse' factor while shading, before it is multiplied with Material color Buttons are in new Panel 'Amb Occ" in F8 menu. Note: - "Dist:" by shortening the length of rays you get subtler effects and it renders faster too - "DistF:" the attennuation factor gives control over how the 'shadow' spreads out. Further it's just raytracing, so tends to be slooooow.... :) Here same tricks as for other raytraced scenes apply, especially try to keep the environment as small as possible (exclude faces from Octree by giving them no Material Traceable). I still have to think over a couple of aspects, will await feedback on it: - AO color? Now it just adds 'white' - other sampling patterns? I tried dithering, which was so-so - method of controlling final 'samples' in F10? Might be useful for other oversampling too (area light) to have it reacting to a percentage or so..
-rw-r--r--source/blender/blenkernel/intern/world.c5
-rw-r--r--source/blender/blenloader/intern/readfile.c8
-rw-r--r--source/blender/makesdna/DNA_world_types.h18
-rw-r--r--source/blender/render/intern/include/rendercore.h1
-rw-r--r--source/blender/render/intern/source/ray.c100
-rw-r--r--source/blender/render/intern/source/rendercore.c20
-rw-r--r--source/blender/src/buttons_shading.c39
7 files changed, 188 insertions, 3 deletions
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index a5872c0abe9..a31c33e76e6 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -198,6 +198,11 @@ void init_render_world()
R.wrld.miststa+= (float)fabs(R.viewmat[3][2]);
}
}
+
+ /* ambient occlusion */
+ R.wrld.aototsamp= R.wrld.aosamp*R.wrld.aosamp;
+
+
}
else {
memset(&R.wrld, 0, sizeof(World));
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 4797e85d2f4..9f6ba376180 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -4119,6 +4119,7 @@ static void do_versions(Main *main)
}
if(main->versionfile <= 232) {
Tex *tex= main->tex.first;
+ World *wrld= main->world.first;
while(tex) {
/* copied from kernel texture.c */
@@ -4138,6 +4139,13 @@ static void do_versions(Main *main)
tex= tex->id.next;
}
+
+ while(wrld) {
+ if(wrld->aodist==0.0) wrld->aodist= 10.0;
+ if(wrld->aosamp==0.0) wrld->aosamp= 5;
+ wrld= wrld->id.next;
+ }
+
}
diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h
index efa17af4996..c325c2d1b8a 100644
--- a/source/blender/makesdna/DNA_world_types.h
+++ b/source/blender/makesdna/DNA_world_types.h
@@ -91,8 +91,13 @@ typedef struct World {
float starsize, starmindist;
float stardist, starcolnoise;
+ /* unused now: DOF */
short dofsta, dofend, dofmin, dofmax;
-
+
+ /* ambient occlusion */
+ float aodist, aodistfac;
+ short aomode, aosamp, aomix, aototsamp;
+
int physicsEngine;
struct Ipo *ipo;
@@ -117,6 +122,17 @@ typedef struct World {
#define WO_STARS 2
#define WO_DOF 4
#define WO_ACTIVITY_CULLING 8
+#define WO_AMB_OCC 16
+
+/* aomix */
+#define WO_AOADD 0
+#define WO_AOSUB 1
+#define WO_AOADDSUB 2
+
+/* aomode (use distances & random sampling modes) */
+#define WO_AODIST 1
+#define WO_AORNDSMP 2
+
/* mapto */
#define WOMAP_BLEND 1
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
index 288ff10937f..2daf4c2c299 100644
--- a/source/blender/render/intern/include/rendercore.h
+++ b/source/blender/render/intern/include/rendercore.h
@@ -75,6 +75,7 @@ float spec(float inp, int hard);
extern void ray_shadow(ShadeInput *, LampRen *, float *, int);
extern void ray_trace(ShadeInput *, ShadeResult *, int);
+extern void ray_ao(ShadeInput *, World *, float *);
/**
* Apply the background (sky). Depending on the active alphamode and
diff --git a/source/blender/render/intern/source/ray.c b/source/blender/render/intern/source/ray.c
index 00bb576aea8..dc736b85e22 100644
--- a/source/blender/render/intern/source/ray.c
+++ b/source/blender/render/intern/source/ray.c
@@ -425,8 +425,8 @@ void freeoctree(void)
// printf("branches %d nodes %d\n", branchcount, nodecount);
-// printf("raycount %d \n", raycount);
-// printf("ray coherent %d \n", coherent_ray);
+ printf("raycount %d \n", raycount);
+ printf("ray coherent %d \n", coherent_ray);
// printf("accepted %d rejected %d\n", accepted, rejected);
branchcount= 0;
@@ -1844,6 +1844,102 @@ int ray_trace_shadow_rad(ShadeInput *ship, ShadeResult *shr)
return 1;
}
+/* aolight: function to create random unit sphere vectors for total random sampling */
+#include <BLI_rand.h>
+void RandomSpherical(float *v)
+{
+ float r;
+ v[2] = 2.f*BLI_frand()-1.f;
+ if ((r = 1.f - v[2]*v[2])>0.f) {
+ float a = 6.283185307f*BLI_frand();
+ r = sqrt(r);
+ v[0] = r * cos(a);
+ v[1] = r * sin(a);
+ }
+ else v[2] = 1.f;
+}
+
+
+/* extern call from shade_lamp_loop, ambient occlusion calculus */
+void ray_ao(ShadeInput *shi, World *wrld, float *shadfac)
+{
+ Isect isec;
+ float nrm[3], vec[3], ru[3], rv[3];
+ float d, z1, z2, sqz1, sz2, cz2, sh=0;
+ int grid = wrld->aosamp;
+ float gdiv = 1.0/grid;
+ float gdiv2p = gdiv*2.0*M_PI;
+ float maxdist = wrld->aodist;
+ int x, y;
+ int j=0;
+
+ VECCOPY(isec.start, shi->co);
+ isec.vlrorig= shi->vlr;
+ isec.mode= DDA_SHADOW;
+ coh_test= 0; // reset coherence optimize
+
+ VECCOPY(nrm, shi->vn);
+ if ((nrm[0]==0.0) && (nrm[1]==0.0)) {
+ if (nrm[2]<0) ru[0]=-1; else ru[0]=1;
+ ru[1] = ru[2] = 0;
+ rv[0] = rv[2] = 0;
+ rv[1] = 1;
+ }
+ else {
+ ru[0] = nrm[1];
+ ru[1] = -nrm[0];
+ ru[2] = 0.0;
+ d = ru[0]*ru[0] + ru[1]*ru[1];
+ if (d!=0) {
+ d = 1.0/sqrt(d);
+ ru[0] *= d;
+ ru[1] *= d;
+ }
+ Crossf(rv, nrm, ru);
+ }
+
+ for (x=0;x<grid;x++) {
+ for (y=0;y<grid;y++) {
+ if (wrld->aomode & WO_AORNDSMP) {
+ /* total random sampling */
+ RandomSpherical(vec);
+ if ((vec[0]*nrm[0] + vec[1]*nrm[1] + vec[2]*nrm[2]) < 0.0) {
+ vec[0] = -vec[0];
+ vec[1] = -vec[1];
+ vec[2] = -vec[2];
+ }
+ }
+ else {
+ /* stratified uniform sampling */
+ z1 = (x + BLI_frand()) * gdiv;
+ z2 = (y + BLI_frand()) * gdiv2p;
+ if ((sqz1 = 1.0-z1*z1)<0) sqz1=0; else sqz1=sqrt(sqz1);
+ sz2 = sin(z2);
+ cz2 = cos(z2);
+ vec[0] = sqz1*(cz2*ru[0] + sz2*rv[0]) + nrm[0]*z1;
+ vec[1] = sqz1*(cz2*ru[1] + sz2*rv[1]) + nrm[1]*z1;
+ vec[2] = sqz1*(cz2*ru[2] + sz2*rv[2]) + nrm[2]*z1;
+ }
+ isec.end[0] = shi->co[0] - maxdist*vec[0];
+ isec.end[1] = shi->co[1] - maxdist*vec[1];
+ isec.end[2] = shi->co[2] - maxdist*vec[2];
+ if (R.r.mode & R_OSA) {
+ isec.start[0]= shi->co[0] + (jit[j][0]-0.5)*O.dxco[0] + (jit[j][1]-0.5)*O.dyco[0] ;
+ isec.start[1]= shi->co[1] + (jit[j][0]-0.5)*O.dxco[1] + (jit[j][1]-0.5)*O.dyco[1] ;
+ isec.start[2]= shi->co[2] + (jit[j][0]-0.5)*O.dxco[2] + (jit[j][1]-0.5)*O.dyco[2] ;
+ j = ((j+1) % R.osa);
+ }
+ if (d3dda(&isec)) {
+ if (wrld->aomode & WO_AODIST) sh+=exp(-isec.labda*wrld->aodistfac); else sh+=1.0;
+ }
+ }
+ }
+
+ shadfac[3] = 1.0 - (sh/(float)wrld->aototsamp);
+
+}
+
+
/* extern call from shade_lamp_loop */
void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac, int mask)
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index 75ef82658f4..1055e564beb 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -1640,6 +1640,24 @@ void shade_color(ShadeInput *shi, ShadeResult *shr)
shr->alpha= ma->alpha;
}
+static void ambient_occlusion(World *wrld, ShadeInput *shi, ShadeResult *shr)
+{
+ float f, shadfac[4];
+
+ if(wrld->mode & WO_AMB_OCC) {
+ ray_ao(shi, wrld, shadfac);
+
+ if (wrld->aomix==WO_AOADDSUB) shadfac[3] = 2.0*shadfac[3]-1.0;
+ else if (wrld->aomix==WO_AOSUB) shadfac[3] = -(1.0-shadfac[3]);
+
+ f= shadfac[3]*shi->matren->amb;
+ shr->diff[0] += f;
+ shr->diff[1] += f;
+ shr->diff[2] += f;
+ }
+}
+
+
/* mask is used to define the amount of rays/samples */
void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr, int mask)
{
@@ -1747,6 +1765,8 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr, int mask)
}
else shr->diff[0]= shr->diff[1]= shr->diff[2]= ma->emit;
+ ambient_occlusion(&R.wrld, shi, shr);
+
for(a=0; a<R.totlamp; a++) {
lar= R.la[a];
diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c
index 92fd7367209..7fab5d569f8 100644
--- a/source/blender/src/buttons_shading.c
+++ b/source/blender/src/buttons_shading.c
@@ -1688,6 +1688,44 @@ static void world_panel_mistaph(World *wrld)
}
+static void world_panel_amb_occ(World *wrld)
+{
+ uiBlock *block;
+
+ block= uiNewBlock(&curarea->uiblocks, "world_panel_amb_oc", UI_EMBOSS, UI_HELV, curarea->win);
+ uiNewPanelTabbed("Mist / Stars / Physics", "World");
+ if(uiNewPanel(curarea, block, "Amb Occ", "World", 320, 0, 318, 204)==0) return;
+
+ uiBlockSetCol(block, TH_BUT_SETTING1);
+ uiDefButS(block, TOG|BIT|4,B_REDR, "Ambient Occlusion",10,150,300,19, &wrld->mode, 0, 0, 0, 0, "Toggles starfield generation");
+ uiBlockSetCol(block, TH_AUTO);
+
+ if(wrld->mode & WO_AMB_OCC) {
+
+ /* aolight: samples */
+ uiBlockBeginAlign(block);
+ uiDefButS(block, NUM, 0, "Samples:", 10, 120, 150, 19, &wrld->aosamp, 1.0, 16.0, 100, 0, "Sets the number of samples used for AO (actual number: squared)");
+ /* enable/disable total random sampling */
+ uiDefButS(block, TOG|BIT|1, 0, "Random Sampling", 160, 120, 150, 19, &wrld->aomode, 0, 0, 0, 0, "When enabled, total random sampling will be used for an even noisier effect");
+ uiBlockEndAlign(block);
+
+ uiDefButF(block, NUM, 0, "Dist:", 10, 95, 150, 19, &wrld->aodist, 0.001, 5000.0, 100, 0, "Sets length of AO rays, defines how far away other faces give occlusion effect");
+
+ uiBlockBeginAlign(block);
+ uiDefButS(block, TOG|BIT|0, B_REDR, "Use Distances", 10, 70, 150, 19, &wrld->aomode, 0, 0, 0, 0, "When enabled, distances to objects will be used to attenuate shadows");
+ /* distance attenuation factor */
+ if (wrld->aomode & WO_AODIST)
+ uiDefButF(block, NUM, 0, "DistF:", 160, 70, 150, 19, &wrld->aodistfac, 0.00001, 10.0, 100, 0, "Distance factor, the higher, the 'shorter' the shadows");
+
+ /* result mix modes */
+ uiBlockBeginAlign(block);
+ uiDefButS(block, ROW, B_REDR, "Add", 10, 45, 100, 20, &wrld->aomix, 1.0, (float)WO_AOADD, 0, 0, "adds light/shadows");
+ uiDefButS(block, ROW, B_REDR, "Sub", 110, 45, 100, 20, &wrld->aomix, 1.0, (float)WO_AOSUB, 0, 0, "subtracts light/shadows (needs at least one normal light to make anything visible)");
+ uiDefButS(block, ROW, B_REDR, "Both", 210, 45, 100, 20, &wrld->aomix, 1.0, (float)WO_AOADDSUB, 0, 0, "both lightens & darkens");
+ }
+
+}
+
static void world_panel_world(World *wrld)
{
uiBlock *block;
@@ -2757,6 +2795,7 @@ void world_panels()
if(wrld) {
world_panel_mistaph(wrld);
+ world_panel_amb_occ(wrld);
world_panel_texture(wrld);
world_panel_mapto(wrld);
}