Compare commits
743 Commits
temp-cycle
...
smooth-cur
Author | SHA1 | Date | |
---|---|---|---|
240e5c0d60 | |||
4c2a8f568b | |||
fc4a6213d4 | |||
2c341818f7 | |||
7cd18293e1 | |||
d54ddc74a2 | |||
855d2955c4 | |||
8ef39d5c88 | |||
5bd8ac9abf | |||
9a9e9b1c4d | |||
904831e62e | |||
1a7dda046b | |||
82466852fe | |||
fbb4be061c | |||
87cc8550e2 | |||
ccf1bb11b6 | |||
9ae35fafb6 | |||
7c3b435c3a | |||
9cc7e32f39 | |||
9f0acc2c9e | |||
300abf241e | |||
9da098536d | |||
3aaf908719 | |||
a67aae98fe | |||
163a196f29 | |||
b895c7337e | |||
a8bd08ffdd | |||
e91f9f664d | |||
d84f559555 | |||
ec50734106 | |||
a8c7f1329b | |||
9b7d506779 | |||
2deeec9e28 | |||
![]() |
9ca3d4cbbd | ||
0bee126977 | |||
c9d653e560 | |||
1ae3056261 | |||
5f17d47629 | |||
edded659c6 | |||
95d871c1a2 | |||
4b90830cac | |||
a1e8ef264f | |||
f5d02f055f | |||
ed0429e7e6 | |||
27c42e05c4 | |||
374ddd022c | |||
8a254b6271 | |||
8193e50fd3 | |||
8c4b4fdd14 | |||
5fd4eca8c0 | |||
6fec06926e | |||
bb92bb5329 | |||
7997646c2d | |||
0ed5605bd5 | |||
76e8dcafa3 | |||
73cdf00ea8 | |||
![]() |
ecdb16d1d8 | ||
022b9676b0 | |||
e9ca9dd5d7 | |||
82a6889d83 | |||
a5213924a8 | |||
42760d922e | |||
6f4a0c23cc | |||
fc26280bcb | |||
75e392ae9f | |||
6825439b36 | |||
f2aa9bec9d | |||
8cb217069e | |||
9997f5ca91 | |||
63e21e7218 | |||
dd84324485 | |||
d2f20aed04 | |||
c0a9fdd93f | |||
e00f3a6565 | |||
6692af3997 | |||
058a358e98 | |||
ba600ff7fa | |||
fd0fbf2564 | |||
beea9421bd | |||
7b397cdfc8 | |||
d48f4b61c9 | |||
9bc5549222 | |||
6bc962d7bc | |||
e6830167e2 | |||
f21020f45f | |||
455c016ba6 | |||
6e7d962118 | |||
210f839e93 | |||
b1d998ec5d | |||
78c288d377 | |||
2307ea88b5 | |||
8138082ab8 | |||
265d620179 | |||
2ff041b7a5 | |||
edd0dbd23b | |||
8604557b75 | |||
a52ec5308f | |||
0cb38b2875 | |||
6f935dbb38 | |||
![]() |
10764d31d4 | ||
69c389fd63 | |||
686b8e8fed | |||
0aae208749 | |||
3689be736b | |||
9a239eea68 | |||
28451a9cec | |||
efa840f99f | |||
518d690628 | |||
35f5d80f3a | |||
0d86bc9f98 | |||
ff47118c73 | |||
0146ab2fd5 | |||
e54df78c82 | |||
909320e3ff | |||
fa34f864a2 | |||
205202361c | |||
fb73cee1ec | |||
8ae6e35923 | |||
ade9fc9245 | |||
5e9132b3b7 | |||
f934f54b84 | |||
ebd51a022a | |||
13d324f26b | |||
636289b755 | |||
c1e177ad29 | |||
702e9c556f | |||
a372638a76 | |||
2b7edb77c9 | |||
b425e94381 | |||
becb413f29 | |||
66110c6b98 | |||
f815aa01eb | |||
b6cb7b2c92 | |||
09eac0159d | |||
fb1cd7648f | |||
393ba0cf16 | |||
214bbd4c02 | |||
f3782c0a9e | |||
e2a7e1e494 | |||
87d5e34453 | |||
e038830650 | |||
2eb2655181 | |||
9b22dbcc0d | |||
05f377805b | |||
d41acacc61 | |||
38eabcb858 | |||
304e5541cb | |||
c694f6e3fa | |||
1bd9531fda | |||
4003409430 | |||
f1d6bad4b6 | |||
![]() |
920bff5224 | ||
![]() |
129c3ac7b3 | ||
ec22809025 | |||
3e8b2288f5 | |||
5c963128ea | |||
17230ec11f | |||
320fc70cf2 | |||
66e28a2827 | |||
edc6bec9d6 | |||
35d9f68121 | |||
d1dc5e0a53 | |||
e93804318f | |||
![]() |
b7fb00f512 | ||
7260a693e1 | |||
c75f6d9245 | |||
7fbd529fb5 | |||
7f09b55d01 | |||
b379f02f20 | |||
![]() |
c3c0495b30 | ||
f65a8bbdb7 | |||
9e929c911e | |||
e982ebd6d4 | |||
ec831ee7d1 | |||
b4528d8897 | |||
a27b6ae4a9 | |||
70eac432b7 | |||
9e40977c27 | |||
34f0250f32 | |||
11204fce4e | |||
4d67034076 | |||
2200e5a280 | |||
8b17ec0c00 | |||
dc6fcb8ecf | |||
db8bc1d982 | |||
0d4fd7528f | |||
2b132fc3f7 | |||
a4cd7b7297 | |||
3b12a71972 | |||
![]() |
c1ca3c8038 | ||
![]() |
4bc6faf9c8 | ||
6e90294e08 | |||
73adf3e27d | |||
5376b3eeca | |||
3daa641d7f | |||
8b2785bda5 | |||
3cfb248bb6 | |||
ecb5b55d7f | |||
2174a2118b | |||
7784cf30eb | |||
5f35682f3a | |||
d8906f30d3 | |||
66383ea206 | |||
16fc2ad28e | |||
9bbb197d14 | |||
d268cad06a | |||
f05f2f0336 | |||
9feeb14e91 | |||
06505c5264 | |||
d4246476d0 | |||
d0aa620912 | |||
bc8a9c47c6 | |||
3d1e5bca88 | |||
4e22e24689 | |||
2d0c9542fe | |||
7021aa245d | |||
5c30bc285c | |||
49c29dc82f | |||
8009564503 | |||
08b59ab7b9 | |||
5fb5b74890 | |||
c6ddef7359 | |||
0f793ee606 | |||
c9817c67fc | |||
7daae642d8 | |||
a651f5da66 | |||
248bba81e7 | |||
e656dcd365 | |||
d3f7b04f04 | |||
2771f602e6 | |||
457596d4df | |||
87164114a3 | |||
8603424d0a | |||
1f933c94a7 | |||
29ec0b1162 | |||
3f39719b5d | |||
b3f62b68a9 | |||
dd1edb0954 | |||
32edfd53d9 | |||
085ed00e42 | |||
cd3b3e4a57 | |||
fdfcbfd040 | |||
b452003015 | |||
e26f61a2b5 | |||
36ef6ff66b | |||
d5d7d453a5 | |||
1dfc4be6ab | |||
d415a1cbd6 | |||
218c254e72 | |||
a247b367b0 | |||
8677c76f13 | |||
665288ccd7 | |||
46b9124241 | |||
806bc4b433 | |||
9a4cfc3e77 | |||
440c91b1f6 | |||
5b1c1d4d23 | |||
910ab14145 | |||
2c10e8a3cf | |||
c055536d23 | |||
004a143760 | |||
2acd05b24c | |||
00f3ab2fb2 | |||
ba256b32ee | |||
0584c5ba8e | |||
3361f2107b | |||
dbaaff2e09 | |||
7dc3ad2287 | |||
1e21778261 | |||
4d4ebc8300 | |||
00d476976e | |||
fee7f688c3 | |||
d25ccf83ad | |||
aaec4ed07d | |||
28a9d7ec6e | |||
a7a5c20fbc | |||
bdd814d87d | |||
9c3f1ad003 | |||
95b345b2fe | |||
f9963f29e8 | |||
222b96e5c7 | |||
cff172c762 | |||
aea4456101 | |||
31f8ca5034 | |||
d2f748a222 | |||
5e9ad8065a | |||
fed853ea78 | |||
e3bddcb215 | |||
d37dd97e45 | |||
58c456b12d | |||
4d124418b7 | |||
f86b43e130 | |||
d1dfd5fa26 | |||
b87d10d4fe | |||
3edc8c1f9b | |||
15fd758bd6 | |||
6782a6076c | |||
56422ff6c3 | |||
1fb3075803 | |||
0900914d96 | |||
7b12957267 | |||
95a97f79cc | |||
44397a7a0a | |||
d48a9528ca | |||
f5535fcb83 | |||
cda24d0853 | |||
46c7d45f77 | |||
0c122d64d2 | |||
![]() |
405121d613 | ||
3232d8ec8f | |||
e3e5ecfaa8 | |||
eb1532a860 | |||
29c8c50442 | |||
eb420e6b7f | |||
52b9516e03 | |||
79f27fc8d3 | |||
5b2b5a4258 | |||
9cd6b03187 | |||
76eefa5c0d | |||
1938a81e42 | |||
c8fa716c06 | |||
56dcfcce05 | |||
9c2bbfb6ce | |||
9210a4faf3 | |||
eb88f0c321 | |||
0210c6b9de | |||
a57a7975a1 | |||
1f3fd8e60a | |||
b5696f2799 | |||
16eca8f47e | |||
2c0ee61f6d | |||
![]() |
f11bcbed9d | ||
bb0e8f1c55 | |||
b796ce0f26 | |||
5a1bdf2c3a | |||
d4ca2ec9d5 | |||
3c2f0466d8 | |||
0172ed8fe5 | |||
b0ee9aaa5d | |||
957a77c0ba | |||
c822b1612f | |||
1c053c6a12 | |||
ad58617bd2 | |||
c9b95c28f6 | |||
fcb8761966 | |||
1340c7bcdc | |||
d17786b107 | |||
bdacb60a92 | |||
ddabe465b5 | |||
a2a301bdb9 | |||
89060babbc | |||
0d2b1da3a6 | |||
ce531ed1a1 | |||
f51438aea0 | |||
![]() |
c2d285f0ff | ||
bddb4de47c | |||
7abed4e433 | |||
![]() |
be4b5551c7 | ||
1979176088 | |||
8cb741a598 | |||
968093ec2f | |||
14ea0c5fcc | |||
![]() |
22466a5bdf | ||
af35455912 | |||
9e08019b74 | |||
e3b1d562a7 | |||
243b42af49 | |||
81775e1920 | |||
7461bb3f52 | |||
c9291ab2ac | |||
9af3119c53 | |||
24486513d5 | |||
5347aa40d5 | |||
1addac8e0c | |||
e917bc5ee0 | |||
0d5c7e5e36 | |||
e9aaf5ed21 | |||
72c9141a7a | |||
3190eaf109 | |||
f158a206f2 | |||
cd8c46627f | |||
b94a433ca3 | |||
1ec987f73c | |||
8bf108dd48 | |||
ed6d88f06a | |||
fc4154f857 | |||
34389999b2 | |||
794311c92b | |||
18e1c8d9fa | |||
a348023196 | |||
127a754615 | |||
6b502731a5 | |||
1d966ca7a1 | |||
3d03616772 | |||
880e96dd66 | |||
9e0a253ea1 | |||
ddb8330571 | |||
ee5ed2ae26 | |||
2bd51474a4 | |||
7853ebc204 | |||
25c0666b90 | |||
7a80c34f52 | |||
b488988ab1 | |||
038b73bab1 | |||
692ce81d93 | |||
a96030b3da | |||
44fd84bcc3 | |||
df7c609fda | |||
eeb9e5316a | |||
31437b0d4d | |||
5e485e34e8 | |||
9a0673a5d4 | |||
e1983adef4 | |||
481cf2982b | |||
20e5052a72 | |||
97f9f90986 | |||
1e6ad49dca | |||
bbd0d43417 | |||
64aa0cff89 | |||
2462320210 | |||
f02e04f133 | |||
6becdf5d00 | |||
90bc882068 | |||
![]() |
6cfa3ecd4d | ||
40c04dd649 | |||
0aa5431998 | |||
85fafccb4c | |||
d8957e4cce | |||
1ba6ef25b6 | |||
987ec1d030 | |||
00c4f49a6d | |||
5ccaef6d67 | |||
1bd6ed7128 | |||
![]() |
04530c9383 | ||
![]() |
09eb11363e | ||
eb1cde5a81 | |||
dfd8b38e0c | |||
558bea2252 | |||
![]() |
0dd6e5bfee | ||
e097fc4aa6 | |||
eb293f59f2 | |||
6238214159 | |||
32299d32e7 | |||
6995b50e41 | |||
4360e8ce13 | |||
ea846a4dfc | |||
![]() |
1f0998baa7 | ||
c73206acc5 | |||
0a898e2405 | |||
7dc51f87ed | |||
f0bbb67e8a | |||
e0bc5b533c | |||
f097e73a2a | |||
d7f33668d6 | |||
d583af0026 | |||
ab4b7b5368 | |||
a46a168705 | |||
58de2164c9 | |||
03a5da0a63 | |||
705c43be0b | |||
8a757bf34a | |||
46c073e4ac | |||
c71e160c02 | |||
6a546fc73e | |||
45d3e22204 | |||
78c0f09d4f | |||
ff6b249046 | |||
d25ab3fcc4 | |||
2bd49785f9 | |||
7667040dd0 | |||
89d4164f54 | |||
ed84388e7d | |||
a3bb309275 | |||
b31e84a4b3 | |||
8be55193c9 | |||
5489b40a5a | |||
3fe73c72d6 | |||
![]() |
29ace10f7e | ||
58a434b372 | |||
1846627ae0 | |||
81d7ff8476 | |||
bd8377cb5a | |||
7bff00b522 | |||
556942ec07 | |||
![]() |
420d4a70b8 | ||
863f0434ec | |||
0d8bf4bf94 | |||
![]() |
e1910ac6ed | ||
020bbbb046 | |||
3be073807b | |||
e5d8b04abe | |||
df7d38c111 | |||
a72daea36e | |||
3a7361ec39 | |||
6799fb387d | |||
5bda458bce | |||
a4925b05a7 | |||
d492ae8893 | |||
a13aa12d7c | |||
a6bb98aef9 | |||
d5d7455796 | |||
528ae8885e | |||
e2b1c70b48 | |||
8b0f968a31 | |||
f783efd127 | |||
a481908232 | |||
2ae6973936 | |||
a51dccc6f3 | |||
140d9a9b15 | |||
ec804b1694 | |||
![]() |
c91d2d30df | ||
![]() |
2cd7b80cae | ||
![]() |
9cae631059 | ||
d1d359b792 | |||
f92fc950c2 | |||
03469d90b2 | |||
b62a7767a0 | |||
34cb934343 | |||
be59428877 | |||
24a0b332e2 | |||
35f4abcf53 | |||
4e5440686d | |||
916eca6a1e | |||
4aeba3b90d | |||
cfce8623a8 | |||
71dcead790 | |||
aab3a0fda3 | |||
31bc9beeac | |||
7eceb756e4 | |||
47aedb97b6 | |||
15692c8cfe | |||
fb82948043 | |||
6c16130356 | |||
2c515df83d | |||
46da985c8e | |||
76c97aaff9 | |||
9b914764a9 | |||
6757ca8b40 | |||
538fe7d48e | |||
f2d7356f16 | |||
f212bfa3cd | |||
06ca2c9d03 | |||
08b7955415 | |||
2fb56e7157 | |||
be31582e3d | |||
ea147e9a28 | |||
ecf2f1593a | |||
94a3bc63cc | |||
5f46374c89 | |||
8051f2412e | |||
9ba7805a3b | |||
b947810291 | |||
9f044cb422 | |||
275e2fb0ff | |||
7df5ed14b1 | |||
2eead82ce0 | |||
19809c8385 | |||
4d58080e23 | |||
b0015686e2 | |||
ac66fb193f | |||
bddd9d809d | |||
bf5e717ef5 | |||
f78ba0df02 | |||
98df7d778f | |||
b5a976ec19 | |||
4badf67739 | |||
9158d16219 | |||
0021268311 | |||
3722ed13cd | |||
2bc008e8a9 | |||
dc23b48101 | |||
1358c39455 | |||
9179797811 | |||
2580c3cb82 | |||
1ddf67382b | |||
24e3a930f1 | |||
bbce6ce249 | |||
a033a7bef9 | |||
55c15ad9de | |||
3de9db9650 | |||
f4074ce8d7 | |||
d252ac6b95 | |||
6715bfee92 | |||
e921e0f0af | |||
eafea25c41 | |||
d5d9d1fe7d | |||
ad27e97ee7 | |||
![]() |
e20a33b89d | ||
7b25ffb618 | |||
cc0cc880de | |||
96e068d3aa | |||
c1b321e1b8 | |||
116e8933a6 | |||
49cc78ef18 | |||
72d67ba4c2 | |||
8d26f2c222 | |||
7add6b89bc | |||
9b29233800 | |||
8cc4c3da8c | |||
849e77b1f9 | |||
f08f8a2df2 | |||
e3d6321530 | |||
81667b770c | |||
f5a9f150dc | |||
9737401688 | |||
34b689892b | |||
baf788d7cd | |||
bd09b51379 | |||
f3d9f0c779 | |||
3bf69b26ef | |||
96769f3b19 | |||
38a2bf665b | |||
81e584ed17 | |||
6cd1d34dc1 | |||
3dee1f079f | |||
177385dc43 | |||
b6f5e8d9a1 | |||
8d4aff31ce | |||
0e46da76b7 | |||
a7c4b6f49c | |||
ef549b9e55 | |||
908bb8bd82 | |||
90a62404cb | |||
3a634524e3 | |||
de86da521c | |||
803337f3f6 | |||
8e655446d1 | |||
a5c73129c5 | |||
ec051f5103 | |||
edbd3ebcdc | |||
4a04d7ae89 | |||
cf1127f380 | |||
29f4a8510c | |||
a21277b996 | |||
ffd83a34ab | |||
740cd28748 | |||
b3a3459e1a | |||
9586cc4708 | |||
6bf05ab2ca | |||
49bd3d3a1a | |||
1247f609d4 | |||
![]() |
32c9d2322c | ||
208462e424 | |||
102394a323 | |||
c4d122e305 | |||
9a910443c4 | |||
1d49205b1a | |||
cc2755b443 | |||
47f8459ead | |||
f674bc90e2 | |||
![]() |
40e6f65ea1 | ||
24676b535a | |||
0a6c57d3d2 | |||
966a2681f9 | |||
e14a2e87dc | |||
d59721c2c3 | |||
26b2323189 | |||
8be9d68dd4 | |||
a70a7f9db3 | |||
f89c6e739a | |||
![]() |
06ac6ded66 | ||
f6afd1b73c | |||
d508b69e44 | |||
12651aba03 | |||
15e8fbd549 | |||
4621583612 | |||
5319571511 | |||
1c21e088f2 | |||
ef8ad66aa2 | |||
1f96dd2e0b | |||
![]() |
b60f80e9b3 | ||
df94f2f399 | |||
b5b72a3f29 | |||
687ff699e9 | |||
890d871bc3 | |||
8ca9fa5fd3 | |||
37bc3850ce | |||
868678c85f | |||
77d633399c | |||
8eeb610832 | |||
![]() |
6b9ab1f7a2 | ||
15038975a3 | |||
![]() |
90b9467861 | ||
bb376c6693 | |||
c95a8bc68f | |||
58a0c27546 | |||
f4b7c33c1a | |||
edd7c55796 | |||
722bcb554f | |||
b82954f6f4 | |||
42c346028f | |||
8246246bda | |||
![]() |
62aa925c11 | ||
![]() |
195d0fbae3 | ||
![]() |
d2f1f80a6f | ||
9395646c2c | |||
894513c7fd | |||
4d38932cb4 | |||
e20eb2dec0 | |||
98ab2c682d | |||
ffc95a33b6 | |||
06b2f10ad1 | |||
378d44daef | |||
586ab120e5 | |||
0f561da5fb | |||
717d85fb1c | |||
49523c4d0e | |||
a1442b7cea | |||
5e82981f47 | |||
1cfc48192c | |||
415ff7467c | |||
ce28025eaf | |||
e518ea9b5e | |||
c9451f1cff | |||
3cd27374ee | |||
43b374e8c5 | |||
bca6978347 | |||
ce31a892db | |||
bdb4ecfbdd | |||
5cdd94a58e | |||
0eef40ed51 | |||
89120cd241 | |||
b85f7e288e | |||
2eb906e1b4 | |||
850bb7a50b | |||
622ce5672a | |||
198248fa3d | |||
294ffa0d49 | |||
![]() |
8b97e42eca | ||
![]() |
b9fda4480f | ||
![]() |
f3c3483242 | ||
5b6838129f | |||
52e6a6c5ef | |||
d2cd27a39d | |||
fbf4b2f17a | |||
![]() |
839bf119c1 | ||
57bcc19bb3 | |||
97caad858f | |||
d29e3ebcc6 | |||
ed688e4843 | |||
a523dfd2fd | |||
b180900e52 | |||
e3bc021079 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -21,7 +21,6 @@ Desktop.ini
|
||||
|
||||
# commonly used paths in blender
|
||||
/blender.bin
|
||||
/user-config.py
|
||||
/BUILD_NOTES.txt
|
||||
|
||||
# local patches
|
||||
@@ -34,8 +33,3 @@ Desktop.ini
|
||||
/doc/python_api/sphinx-in/
|
||||
/doc/python_api/sphinx-out/
|
||||
/doc/python_api/rst/bmesh.ops.rst
|
||||
/doc/python_api/rst/in_menu.png
|
||||
/doc/python_api/rst/menu_id.png
|
||||
/doc/python_api/rst/op_prop.png
|
||||
/doc/python_api/rst/run_script.png
|
||||
/doc/python_api/rst/spacebar.png
|
||||
|
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -2,7 +2,7 @@
|
||||
path = release/scripts/addons
|
||||
url = ../blender-addons.git
|
||||
ignore = all
|
||||
branch = master
|
||||
branch = blender-v2.79-release
|
||||
[submodule "release/scripts/addons_contrib"]
|
||||
path = release/scripts/addons_contrib
|
||||
url = ../blender-addons-contrib.git
|
||||
@@ -12,9 +12,9 @@
|
||||
path = release/datafiles/locale
|
||||
url = ../blender-translations.git
|
||||
ignore = all
|
||||
branch = master
|
||||
branch = blender-v2.79-release
|
||||
[submodule "source/tools"]
|
||||
path = source/tools
|
||||
url = ../blender-dev-tools.git
|
||||
ignore = all
|
||||
branch = master
|
||||
branch = blender-v2.79-release
|
||||
|
@@ -32,7 +32,7 @@ if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
|
||||
if(NOT DEFINED WITH_IN_SOURCE_BUILD)
|
||||
message(FATAL_ERROR
|
||||
"CMake generation for blender is not allowed within the source directory!"
|
||||
"\n Remove the CMakeCache.txt file and try again from another folder, e.g.:"
|
||||
"\n Remove \"${CMAKE_SOURCE_DIR}/CMakeCache.txt\" and try again from another folder, e.g.:"
|
||||
"\n "
|
||||
"\n rm CMakeCache.txt"
|
||||
"\n cd .."
|
||||
@@ -58,7 +58,9 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/build_files/cmake/Modules")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/build_files/cmake/platform")
|
||||
|
||||
# avoid having empty buildtype
|
||||
set(CMAKE_BUILD_TYPE_INIT "Release")
|
||||
if(NOT DEFINED CMAKE_BUILD_TYPE_INIT)
|
||||
set(CMAKE_BUILD_TYPE_INIT "Release")
|
||||
endif()
|
||||
|
||||
# quiet output for Makefiles, 'make -s' helps too
|
||||
# set_property(GLOBAL PROPERTY RULE_MESSAGES OFF)
|
||||
@@ -229,7 +231,7 @@ mark_as_advanced(BUILDINFO_OVERRIDE_TIME)
|
||||
|
||||
option(WITH_IK_ITASC "Enable ITASC IK solver (only disable for development & for incompatible C++ compilers)" ON)
|
||||
option(WITH_IK_SOLVER "Enable Legacy IK solver (only disable for development)" ON)
|
||||
option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke and audio effects)" ${_init_FFTW3})
|
||||
option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke, ocean sim, and audio effects)" ${_init_FFTW3})
|
||||
option(WITH_BULLET "Enable Bullet (Physics Engine)" ON)
|
||||
option(WITH_SYSTEM_BULLET "Use the systems bullet library (currently unsupported due to missing features in upstream!)" )
|
||||
mark_as_advanced(WITH_SYSTEM_BULLET)
|
||||
@@ -1380,10 +1382,20 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_MISSING_DECLARATIONS -Wmissing-declarations)
|
||||
endif()
|
||||
|
||||
# Use 'ATTR_FALLTHROUGH' macro to suppress.
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "7.0"))
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_IMPLICIT_FALLTHROUGH -Wimplicit-fallthrough=5)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_IMPLICIT_FALLTHROUGH -Wimplicit-fallthrough=5)
|
||||
endif()
|
||||
|
||||
# flags to undo strict flags
|
||||
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_DEPRECATED_DECLARATIONS -Wno-deprecated-declarations)
|
||||
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "7.0"))
|
||||
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_IMPLICIT_FALLTHROUGH -Wno-implicit-fallthrough)
|
||||
endif()
|
||||
|
||||
if(NOT APPLE)
|
||||
ADD_CHECK_C_COMPILER_FLAG(CC_REMOVE_STRICT_FLAGS C_WARN_NO_ERROR_UNUSED_BUT_SET_VARIABLE -Wno-error=unused-but-set-variable)
|
||||
endif()
|
||||
|
@@ -104,7 +104,7 @@ endif
|
||||
CMAKE_CONFIG = cmake $(BUILD_CMAKE_ARGS) \
|
||||
-H"$(BLENDER_DIR)" \
|
||||
-B"$(BUILD_DIR)" \
|
||||
-DCMAKE_BUILD_TYPE:STRING=$(BUILD_TYPE)
|
||||
-DCMAKE_BUILD_TYPE_INIT:STRING=$(BUILD_TYPE)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
@@ -26,7 +26,7 @@ ARGS=$( \
|
||||
getopt \
|
||||
-o s:i:t:h \
|
||||
--long source:,install:,tmp:,info:,threads:,help,show-deps,no-sudo,no-build,no-confirm,use-cxx11,\
|
||||
with-all,with-opencollada,\
|
||||
with-all,with-opencollada,with-jack,\
|
||||
ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,\
|
||||
force-all,force-python,force-numpy,force-boost,\
|
||||
force-ocio,force-openexr,force-oiio,force-llvm,force-osl,force-osd,force-openvdb,\
|
||||
@@ -118,6 +118,9 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS:
|
||||
--with-opencollada
|
||||
Build and install the OpenCOLLADA libraries.
|
||||
|
||||
--with-jack
|
||||
Install the jack libraries.
|
||||
|
||||
--ver-ocio=<ver>
|
||||
Force version of OCIO library.
|
||||
|
||||
@@ -289,7 +292,7 @@ NO_BUILD=false
|
||||
NO_CONFIRM=false
|
||||
USE_CXX11=false
|
||||
|
||||
PYTHON_VERSION="3.5.2"
|
||||
PYTHON_VERSION="3.5.3"
|
||||
PYTHON_VERSION_MIN="3.5"
|
||||
PYTHON_FORCE_BUILD=false
|
||||
PYTHON_FORCE_REBUILD=false
|
||||
@@ -322,8 +325,8 @@ OPENEXR_FORCE_REBUILD=false
|
||||
OPENEXR_SKIP=false
|
||||
_with_built_openexr=false
|
||||
|
||||
OIIO_VERSION="1.7.13"
|
||||
OIIO_VERSION_MIN="1.7.13"
|
||||
OIIO_VERSION="1.7.15"
|
||||
OIIO_VERSION_MIN="1.7.15"
|
||||
OIIO_VERSION_MAX="1.9.0" # UNKNOWN currently # Not supported by current OSL...
|
||||
OIIO_FORCE_BUILD=false
|
||||
OIIO_FORCE_REBUILD=false
|
||||
@@ -366,8 +369,7 @@ ALEMBIC_FORCE_BUILD=false
|
||||
ALEMBIC_FORCE_REBUILD=false
|
||||
ALEMBIC_SKIP=false
|
||||
|
||||
# Version??
|
||||
OPENCOLLADA_VERSION="1.3"
|
||||
OPENCOLLADA_VERSION="1.6.51"
|
||||
OPENCOLLADA_FORCE_BUILD=false
|
||||
OPENCOLLADA_FORCE_REBUILD=false
|
||||
OPENCOLLADA_SKIP=false
|
||||
@@ -508,6 +510,9 @@ while true; do
|
||||
--with-opencollada)
|
||||
WITH_OPENCOLLADA=true; shift; continue
|
||||
;;
|
||||
--with-jack)
|
||||
WITH_JACK=true; shift; continue;
|
||||
;;
|
||||
--ver-ocio)
|
||||
OCIO_VERSION="$2"
|
||||
OCIO_VERSION_MIN=$OCIO_VERSION
|
||||
@@ -711,6 +716,9 @@ done
|
||||
if [ "$WITH_ALL" = true -a "$OPENCOLLADA_SKIP" = false ]; then
|
||||
WITH_OPENCOLLADA=true
|
||||
fi
|
||||
if [ "$WITH_ALL" = true ]; then
|
||||
WITH_JACK=true
|
||||
fi
|
||||
|
||||
|
||||
WARNING "****WARNING****"
|
||||
@@ -737,7 +745,10 @@ _boost_version_nodots=`echo "$BOOST_VERSION" | sed -r 's/\./_/g'`
|
||||
BOOST_SOURCE=( "http://sourceforge.net/projects/boost/files/boost/$BOOST_VERSION/boost_$_boost_version_nodots.tar.bz2/download" )
|
||||
BOOST_BUILD_MODULES="--with-system --with-filesystem --with-thread --with-regex --with-locale --with-date_time --with-wave --with-iostreams --with-python --with-program_options"
|
||||
|
||||
OCIO_USE_REPO=true
|
||||
OCIO_SOURCE=( "https://github.com/imageworks/OpenColorIO/tarball/v$OCIO_VERSION" )
|
||||
OCIO_SOURCE_REPO=( "https://github.com/imageworks/OpenColorIO.git" )
|
||||
OCIO_SOURCE_REPO_UID="6de971097c7f552300f669ed69ca0b6cf5a70843"
|
||||
|
||||
OPENEXR_USE_REPO=false
|
||||
OPENEXR_SOURCE=( "http://download.savannah.nongnu.org/releases/openexr/openexr-$OPENEXR_VERSION.tar.gz" )
|
||||
@@ -786,7 +797,7 @@ ALEMBIC_SOURCE=( "https://github.com/alembic/alembic/archive/${ALEMBIC_VERSION}.
|
||||
# ALEMBIC_SOURCE_REPO_BRANCH="master"
|
||||
|
||||
OPENCOLLADA_SOURCE=( "https://github.com/KhronosGroup/OpenCOLLADA.git" )
|
||||
OPENCOLLADA_REPO_UID="3335ac164e68b2512a40914b14c74db260e6ff7d"
|
||||
OPENCOLLADA_REPO_UID="0c2cdc17c22cf42050e4d42154bed2176363549c"
|
||||
OPENCOLLADA_REPO_BRANCH="master"
|
||||
|
||||
FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" )
|
||||
@@ -1268,7 +1279,7 @@ compile_OCIO() {
|
||||
fi
|
||||
|
||||
# To be changed each time we make edits that would modify the compiled result!
|
||||
ocio_magic=1
|
||||
ocio_magic=2
|
||||
_init_ocio
|
||||
|
||||
# Clean install if needed!
|
||||
@@ -1285,14 +1296,27 @@ compile_OCIO() {
|
||||
if [ ! -d $_src ]; then
|
||||
INFO "Downloading OpenColorIO-$OCIO_VERSION"
|
||||
mkdir -p $SRC
|
||||
download OCIO_SOURCE[@] $_src.tar.gz
|
||||
|
||||
INFO "Unpacking OpenColorIO-$OCIO_VERSION"
|
||||
tar -C $SRC --transform "s,(.*/?)imageworks-OpenColorIO[^/]*(.*),\1OpenColorIO-$OCIO_VERSION\2,x" \
|
||||
-xf $_src.tar.gz
|
||||
if [ "$OCIO_USE_REPO" = true ]; then
|
||||
git clone ${OCIO_SOURCE_REPO[0]} $_src
|
||||
else
|
||||
download OCIO_SOURCE[@] $_src.tar.gz
|
||||
INFO "Unpacking OpenColorIO-$OCIO_VERSION"
|
||||
tar -C $SRC --transform "s,(.*/?)imageworks-OpenColorIO[^/]*(.*),\1OpenColorIO-$OCIO_VERSION\2,x" \
|
||||
-xf $_src.tar.gz
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
cd $_src
|
||||
|
||||
if [ "$OCIO_USE_REPO" = true ]; then
|
||||
# XXX For now, always update from latest repo...
|
||||
git pull origin master
|
||||
git checkout $OCIO_SOURCE_REPO_UID
|
||||
git reset --hard
|
||||
fi
|
||||
|
||||
# Always refresh the whole build!
|
||||
if [ -d build ]; then
|
||||
rm -rf build
|
||||
@@ -1498,7 +1522,6 @@ compile_OPENEXR() {
|
||||
if [ "$OPENEXR_USE_REPO" = true ]; then
|
||||
# XXX For now, always update from latest repo...
|
||||
git pull origin master
|
||||
# Stick to same rev as windows' libs...
|
||||
git checkout $OPENEXR_SOURCE_REPO_UID
|
||||
git reset --hard
|
||||
oiio_src_path="../OpenEXR"
|
||||
@@ -1576,7 +1599,7 @@ compile_OIIO() {
|
||||
fi
|
||||
|
||||
# To be changed each time we make edits that would modify the compiled result!
|
||||
oiio_magic=16
|
||||
oiio_magic=17
|
||||
_init_oiio
|
||||
|
||||
# Clean install if needed!
|
||||
@@ -1640,6 +1663,9 @@ compile_OIIO() {
|
||||
INFO "ILMBASE_HOME=$INST/openexr"
|
||||
fi
|
||||
|
||||
# ptex is only needed when nicholas bishop is ready
|
||||
cmake_d="$cmake_d -D USE_PTEX=OFF"
|
||||
|
||||
# Optional tests and cmd tools
|
||||
cmake_d="$cmake_d -D USE_QT=OFF"
|
||||
cmake_d="$cmake_d -D USE_PYTHON=OFF"
|
||||
@@ -2638,7 +2664,7 @@ install_DEB() {
|
||||
PRINT ""
|
||||
fi
|
||||
|
||||
if [ "$WITH_ALL" = true ]; then
|
||||
if [ "$WITH_JACK" = true ]; then
|
||||
_packages="$_packages libspnav-dev"
|
||||
# Only install jack if jack2 is not already installed!
|
||||
JACK="libjack-dev"
|
||||
@@ -3175,7 +3201,7 @@ install_RPM() {
|
||||
if [ "$RPM" = "FEDORA" -o "$RPM" = "RHEL" ]; then
|
||||
_packages="$_packages freetype-devel tbb-devel"
|
||||
|
||||
if [ "$WITH_ALL" = true ]; then
|
||||
if [ "$WITH_JACK" = true ]; then
|
||||
_packages="$_packages jack-audio-connection-kit-devel"
|
||||
fi
|
||||
|
||||
@@ -3649,7 +3675,11 @@ install_ARCH() {
|
||||
THEORA_USE=true
|
||||
|
||||
if [ "$WITH_ALL" = true ]; then
|
||||
_packages="$_packages jack libspnav"
|
||||
_packages="$_packages libspnav"
|
||||
fi
|
||||
|
||||
if [ "$WITH_JACK" = true ]; then
|
||||
_packages="$_packages jack"
|
||||
fi
|
||||
|
||||
PRINT ""
|
||||
@@ -4311,6 +4341,14 @@ print_info() {
|
||||
_buildargs="$_buildargs $_1"
|
||||
fi
|
||||
|
||||
if [ "$WITH_JACK" = true ]; then
|
||||
_1="-D WITH_JACK=ON"
|
||||
_2="-D WITH_JACK_DYNLOAD=ON"
|
||||
PRINT " $_1"
|
||||
PRINT " $_2"
|
||||
_buildargs="$_buildargs $_1 $_2"
|
||||
fi
|
||||
|
||||
if [ "$ALEMBIC_SKIP" = false ]; then
|
||||
_1="-D WITH_ALEMBIC=ON"
|
||||
PRINT " $_1"
|
||||
|
@@ -70,7 +70,7 @@ set(FFMPEG_LIBRARIES
|
||||
)
|
||||
|
||||
# SndFile libraries
|
||||
set(SNDFILE_LIBRARY "/usr/lib/libsndfile.a;/usr/lib/libFLAC.a" CACHE STRING "" FORCE)
|
||||
set(SNDFILE_LIBRARY "/usr/lib${MULTILIB}/libsndfile.a;/usr/lib${MULTILIB}/libFLAC.a" CACHE STRING "" FORCE)
|
||||
|
||||
# OpenAL libraries
|
||||
set(OPENAL_ROOT_DIR "/opt/lib/openal" CACHE STRING "" FORCE)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# This is applied as an ovveride on top of blender_linux.config
|
||||
# This is applied as an override on top of blender_linux.config
|
||||
# Disables all the areas which are not needed for the player.
|
||||
set(WITH_COMPOSITOR OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES OFF CACHE BOOL "" FORCE)
|
||||
|
@@ -49,7 +49,7 @@ def get_platform(filename):
|
||||
tokens = filename.split("-")
|
||||
platforms = ('osx', 'mac', 'bsd',
|
||||
'win', 'linux', 'source',
|
||||
'irix', 'solaris', 'mingw')
|
||||
'irix', 'solaris')
|
||||
platform_tokens = []
|
||||
found = False
|
||||
|
||||
|
@@ -112,8 +112,8 @@ if 'cmake' in builder:
|
||||
chroot_name = 'buildbot_' + deb_name + '_i686'
|
||||
cuda_chroot_name = 'buildbot_' + deb_name + '_x86_64'
|
||||
targets = ['player', 'blender', 'cuda']
|
||||
cmake_extra_options.extend(["-DCMAKE_C_COMPILER=/usr/bin/gcc-6",
|
||||
"-DCMAKE_CXX_COMPILER=/usr/bin/g++-6"])
|
||||
cmake_extra_options.extend(["-DCMAKE_C_COMPILER=/usr/bin/gcc-7",
|
||||
"-DCMAKE_CXX_COMPILER=/usr/bin/g++-7"])
|
||||
|
||||
cmake_options.append("-C" + os.path.join(blender_dir, cmake_config_file))
|
||||
|
||||
|
@@ -83,6 +83,7 @@ FOREACH(COMPONENT ${_opencollada_FIND_INCLUDES})
|
||||
# but this is less trouble, just looks strange.
|
||||
include/opencollada/${COMPONENT}
|
||||
include/${COMPONENT}/include
|
||||
include/${COMPONENT}
|
||||
HINTS
|
||||
${_opencollada_SEARCH_DIRS}
|
||||
)
|
||||
|
@@ -61,10 +61,8 @@ def replace_line(f, i, text, keep_indent=True):
|
||||
|
||||
def source_list(path, filename_check=None):
|
||||
for dirpath, dirnames, filenames in os.walk(path):
|
||||
|
||||
# skip '.git'
|
||||
if dirpath.startswith("."):
|
||||
continue
|
||||
dirnames[:] = [d for d in dirnames if not d.startswith(".")]
|
||||
|
||||
for filename in filenames:
|
||||
if filename_check is None or filename_check(filename):
|
||||
|
@@ -63,17 +63,10 @@ if(UNIX AND NOT APPLE)
|
||||
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
|
||||
elseif(WIN32)
|
||||
set(WITH_JACK OFF CACHE BOOL "" FORCE)
|
||||
if(NOT CMAKE_COMPILER_IS_GNUCC)
|
||||
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
|
||||
else()
|
||||
# MinGW exceptions
|
||||
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_OSL OFF CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
|
||||
elseif(APPLE)
|
||||
set(WITH_JACK ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_QUICKTIME OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_QUICKTIME OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
|
||||
|
||||
# include("${CMAKE_CURRENT_SOURCE_DIR}/../platform/platform_apple_xcode.cmake")
|
||||
|
@@ -64,17 +64,10 @@ if(UNIX AND NOT APPLE)
|
||||
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
|
||||
elseif(WIN32)
|
||||
set(WITH_JACK OFF CACHE BOOL "" FORCE)
|
||||
if(NOT CMAKE_COMPILER_IS_GNUCC)
|
||||
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
|
||||
else()
|
||||
# MinGW exceptions
|
||||
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_OSL OFF CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
|
||||
elseif(APPLE)
|
||||
set(WITH_JACK ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_QUICKTIME OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_CODEC_QUICKTIME OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
|
||||
|
||||
# include("${CMAKE_CURRENT_SOURCE_DIR}/../platform/platform_apple_xcode.cmake")
|
||||
|
@@ -1247,17 +1247,6 @@ endfunction()
|
||||
# hacks to override initial project settings
|
||||
# these macros must be called directly before/after project(Blender)
|
||||
macro(blender_project_hack_pre)
|
||||
# ----------------
|
||||
# MINGW HACK START
|
||||
# ignore system set flag, use our own
|
||||
# must be before project(...)
|
||||
# if the user wants to add their own its ok after first run.
|
||||
if(DEFINED CMAKE_C_STANDARD_LIBRARIES)
|
||||
set(_reset_standard_libraries OFF)
|
||||
else()
|
||||
set(_reset_standard_libraries ON)
|
||||
endif()
|
||||
|
||||
# ------------------
|
||||
# GCC -O3 HACK START
|
||||
# needed because O3 can cause problems but
|
||||
@@ -1276,25 +1265,6 @@ endmacro()
|
||||
|
||||
|
||||
macro(blender_project_hack_post)
|
||||
# --------------
|
||||
# MINGW HACK END
|
||||
if(_reset_standard_libraries)
|
||||
# Must come after projecINCt(...)
|
||||
#
|
||||
# MINGW workaround for -ladvapi32 being included which surprisingly causes
|
||||
# string formatting of floats, eg: printf("%.*f", 3, value). to crash blender
|
||||
# with a meaningless stack trace. by overriding this flag we ensure we only
|
||||
# have libs we define.
|
||||
set(CMAKE_C_STANDARD_LIBRARIES "" CACHE STRING "" FORCE)
|
||||
set(CMAKE_CXX_STANDARD_LIBRARIES "" CACHE STRING "" FORCE)
|
||||
mark_as_advanced(
|
||||
CMAKE_C_STANDARD_LIBRARIES
|
||||
CMAKE_CXX_STANDARD_LIBRARIES
|
||||
)
|
||||
endif()
|
||||
unset(_reset_standard_libraries)
|
||||
|
||||
|
||||
# ----------------
|
||||
# GCC -O3 HACK END
|
||||
if(_reset_standard_cflags_rel)
|
||||
|
@@ -27,12 +27,10 @@ add_definitions(-DWIN32)
|
||||
|
||||
if(MSVC)
|
||||
include(platform_win32_msvc)
|
||||
elseif(CMAKE_COMPILER_IS_GNUCC)
|
||||
include(platform_win32_mingw)
|
||||
else()
|
||||
message(FATAL_ERROR "Compiler is unsupported")
|
||||
endif()
|
||||
|
||||
# Things common to both mingw and MSVC should go here
|
||||
|
||||
set(WINTAB_INC ${LIBDIR}/wintab/include)
|
||||
|
||||
if(WITH_OPENAL)
|
||||
|
@@ -1,302 +0,0 @@
|
||||
# ***** 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,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# The Original Code is Copyright (C) 2016, Blender Foundation
|
||||
# All rights reserved.
|
||||
#
|
||||
# Contributor(s): Sergey Sharybin.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
# Libraries configuration for Windows when compiling with MinGW.
|
||||
|
||||
# keep GCC specific stuff here
|
||||
include(CheckCSourceCompiles)
|
||||
# Setup 64bit and 64bit windows systems
|
||||
CHECK_C_SOURCE_COMPILES("
|
||||
#ifndef __MINGW64__
|
||||
#error
|
||||
#endif
|
||||
int main(void) { return 0; }
|
||||
"
|
||||
WITH_MINGW64
|
||||
)
|
||||
|
||||
if(NOT DEFINED LIBDIR)
|
||||
if(WITH_MINGW64)
|
||||
message(STATUS "Compiling for 64 bit with MinGW-w64.")
|
||||
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw64)
|
||||
else()
|
||||
message(STATUS "Compiling for 32 bit with MinGW-w32.")
|
||||
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/mingw32)
|
||||
|
||||
if(WITH_RAYOPTIMIZATION)
|
||||
message(WARNING "MinGW-w32 is known to be unstable with 'WITH_RAYOPTIMIZATION' option enabled.")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
|
||||
endif()
|
||||
if(NOT EXISTS "${LIBDIR}/")
|
||||
message(FATAL_ERROR "Windows requires pre-compiled libs at: '${LIBDIR}'")
|
||||
endif()
|
||||
|
||||
list(APPEND PLATFORM_LINKLIBS
|
||||
-lshell32 -lshfolder -lgdi32 -lmsvcrt -lwinmm -lmingw32 -lm -lws2_32
|
||||
-lz -lstdc++ -lole32 -luuid -lwsock32 -lpsapi -ldbghelp
|
||||
)
|
||||
|
||||
if(WITH_INPUT_IME)
|
||||
list(APPEND PLATFORM_LINKLIBS -limm32)
|
||||
endif()
|
||||
|
||||
set(PLATFORM_CFLAGS "-pipe -funsigned-char -fno-strict-aliasing")
|
||||
|
||||
if(WITH_MINGW64)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive")
|
||||
list(APPEND PLATFORM_LINKLIBS -lpthread)
|
||||
|
||||
add_definitions(-DFREE_WINDOWS64 -DMS_WIN64)
|
||||
endif()
|
||||
|
||||
add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE)
|
||||
|
||||
add_definitions(-DFREE_WINDOWS)
|
||||
|
||||
set(PNG "${LIBDIR}/png")
|
||||
set(PNG_INCLUDE_DIRS "${PNG}/include")
|
||||
set(PNG_LIBPATH ${PNG}/lib) # not cmake defined
|
||||
|
||||
if(WITH_MINGW64)
|
||||
set(JPEG_LIBRARIES jpeg)
|
||||
else()
|
||||
set(JPEG_LIBRARIES libjpeg)
|
||||
endif()
|
||||
set(PNG_LIBRARIES png)
|
||||
|
||||
set(ZLIB ${LIBDIR}/zlib)
|
||||
set(ZLIB_INCLUDE_DIRS ${ZLIB}/include)
|
||||
set(ZLIB_LIBPATH ${ZLIB}/lib)
|
||||
set(ZLIB_LIBRARIES z)
|
||||
|
||||
set(JPEG "${LIBDIR}/jpeg")
|
||||
set(JPEG_INCLUDE_DIR "${JPEG}/include")
|
||||
set(JPEG_LIBPATH ${JPEG}/lib) # not cmake defined
|
||||
|
||||
# comes with own pthread library
|
||||
if(NOT WITH_MINGW64)
|
||||
set(PTHREADS ${LIBDIR}/pthreads)
|
||||
#set(PTHREADS_INCLUDE_DIRS ${PTHREADS}/include)
|
||||
set(PTHREADS_LIBPATH ${PTHREADS}/lib)
|
||||
set(PTHREADS_LIBRARIES pthreadGC2)
|
||||
endif()
|
||||
|
||||
set(FREETYPE ${LIBDIR}/freetype)
|
||||
set(FREETYPE_INCLUDE_DIRS ${FREETYPE}/include ${FREETYPE}/include/freetype2)
|
||||
set(FREETYPE_LIBPATH ${FREETYPE}/lib)
|
||||
set(FREETYPE_LIBRARY freetype)
|
||||
|
||||
if(WITH_FFTW3)
|
||||
set(FFTW3 ${LIBDIR}/fftw3)
|
||||
set(FFTW3_LIBRARIES fftw3)
|
||||
set(FFTW3_INCLUDE_DIRS ${FFTW3}/include)
|
||||
set(FFTW3_LIBPATH ${FFTW3}/lib)
|
||||
endif()
|
||||
|
||||
if(WITH_OPENCOLLADA)
|
||||
set(OPENCOLLADA ${LIBDIR}/opencollada)
|
||||
set(OPENCOLLADA_INCLUDE_DIRS
|
||||
${OPENCOLLADA}/include/opencollada/COLLADAStreamWriter
|
||||
${OPENCOLLADA}/include/opencollada/COLLADABaseUtils
|
||||
${OPENCOLLADA}/include/opencollada/COLLADAFramework
|
||||
${OPENCOLLADA}/include/opencollada/COLLADASaxFrameworkLoader
|
||||
${OPENCOLLADA}/include/opencollada/GeneratedSaxParser
|
||||
)
|
||||
set(OPENCOLLADA_LIBPATH ${OPENCOLLADA}/lib/opencollada)
|
||||
set(OPENCOLLADA_LIBRARIES
|
||||
OpenCOLLADAStreamWriter
|
||||
OpenCOLLADASaxFrameworkLoader
|
||||
OpenCOLLADAFramework
|
||||
OpenCOLLADABaseUtils
|
||||
GeneratedSaxParser
|
||||
UTF MathMLSolver buffer ftoa xml
|
||||
)
|
||||
set(PCRE_LIBRARIES pcre)
|
||||
endif()
|
||||
|
||||
if(WITH_CODEC_FFMPEG)
|
||||
set(FFMPEG ${LIBDIR}/ffmpeg)
|
||||
set(FFMPEG_INCLUDE_DIRS ${FFMPEG}/include)
|
||||
if(WITH_MINGW64)
|
||||
set(FFMPEG_LIBRARIES avcodec.dll avformat.dll avdevice.dll avutil.dll swscale.dll swresample.dll)
|
||||
else()
|
||||
set(FFMPEG_LIBRARIES avcodec-55 avformat-55 avdevice-55 avutil-52 swscale-2)
|
||||
endif()
|
||||
set(FFMPEG_LIBPATH ${FFMPEG}/lib)
|
||||
endif()
|
||||
|
||||
if(WITH_IMAGE_OPENEXR)
|
||||
set(OPENEXR ${LIBDIR}/openexr)
|
||||
set(OPENEXR_INCLUDE_DIR ${OPENEXR}/include)
|
||||
set(OPENEXR_INCLUDE_DIRS ${OPENEXR}/include/OpenEXR)
|
||||
set(OPENEXR_LIBRARIES Half IlmImf Imath IlmThread Iex)
|
||||
set(OPENEXR_LIBPATH ${OPENEXR}/lib)
|
||||
endif()
|
||||
|
||||
if(WITH_IMAGE_TIFF)
|
||||
set(TIFF ${LIBDIR}/tiff)
|
||||
set(TIFF_LIBRARY tiff)
|
||||
set(TIFF_INCLUDE_DIR ${TIFF}/include)
|
||||
set(TIFF_LIBPATH ${TIFF}/lib)
|
||||
endif()
|
||||
|
||||
if(WITH_JACK)
|
||||
set(JACK ${LIBDIR}/jack)
|
||||
set(JACK_INCLUDE_DIRS ${JACK}/include/jack ${JACK}/include)
|
||||
set(JACK_LIBRARIES jack)
|
||||
set(JACK_LIBPATH ${JACK}/lib)
|
||||
|
||||
# TODO, gives linking errors, force off
|
||||
set(WITH_JACK OFF)
|
||||
endif()
|
||||
|
||||
if(WITH_PYTHON)
|
||||
# normally cached but not since we include them with blender
|
||||
set(PYTHON_VERSION 3.5) # CACHE STRING)
|
||||
string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
|
||||
set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}") # CACHE PATH)
|
||||
set(PYTHON_LIBRARY "${LIBDIR}/python/lib/python${_PYTHON_VERSION_NO_DOTS}mw.lib") # CACHE FILEPATH)
|
||||
unset(_PYTHON_VERSION_NO_DOTS)
|
||||
|
||||
# uncached vars
|
||||
set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
|
||||
set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}")
|
||||
endif()
|
||||
|
||||
if(WITH_BOOST)
|
||||
set(BOOST ${LIBDIR}/boost)
|
||||
set(BOOST_INCLUDE_DIR ${BOOST}/include)
|
||||
if(WITH_MINGW64)
|
||||
set(BOOST_POSTFIX "mgw47-mt-s-1_49")
|
||||
set(BOOST_DEBUG_POSTFIX "mgw47-mt-sd-1_49")
|
||||
else()
|
||||
set(BOOST_POSTFIX "mgw46-mt-s-1_49")
|
||||
set(BOOST_DEBUG_POSTFIX "mgw46-mt-sd-1_49")
|
||||
endif()
|
||||
set(BOOST_LIBRARIES
|
||||
optimized boost_date_time-${BOOST_POSTFIX} boost_filesystem-${BOOST_POSTFIX}
|
||||
boost_regex-${BOOST_POSTFIX}
|
||||
boost_system-${BOOST_POSTFIX} boost_thread-${BOOST_POSTFIX}
|
||||
debug boost_date_time-${BOOST_DEBUG_POSTFIX} boost_filesystem-${BOOST_DEBUG_POSTFIX}
|
||||
boost_regex-${BOOST_DEBUG_POSTFIX}
|
||||
boost_system-${BOOST_DEBUG_POSTFIX} boost_thread-${BOOST_DEBUG_POSTFIX})
|
||||
if(WITH_INTERNATIONAL)
|
||||
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
|
||||
optimized boost_locale-${BOOST_POSTFIX}
|
||||
debug boost_locale-${BOOST_DEBUG_POSTFIX}
|
||||
)
|
||||
endif()
|
||||
if(WITH_CYCLES_OSL)
|
||||
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
|
||||
optimized boost_wave-${BOOST_POSTFIX}
|
||||
debug boost_wave-${BOOST_DEBUG_POSTFIX}
|
||||
)
|
||||
endif()
|
||||
set(BOOST_LIBPATH ${BOOST}/lib)
|
||||
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB -DBOOST_THREAD_USE_LIB ")
|
||||
endif()
|
||||
|
||||
if(WITH_OPENIMAGEIO)
|
||||
set(OPENIMAGEIO ${LIBDIR}/openimageio)
|
||||
set(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO}/include)
|
||||
set(OPENIMAGEIO_LIBRARIES OpenImageIO)
|
||||
set(OPENIMAGEIO_LIBPATH ${OPENIMAGEIO}/lib)
|
||||
set(OPENIMAGEIO_DEFINITIONS "")
|
||||
set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe")
|
||||
endif()
|
||||
|
||||
if(WITH_LLVM)
|
||||
set(LLVM_ROOT_DIR ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation")
|
||||
set(LLVM_LIBPATH ${LLVM_ROOT_DIR}/lib)
|
||||
# Explicitly set llvm lib order.
|
||||
#---- WARNING ON GCC ORDER OF LIBS IS IMPORTANT, DO NOT CHANGE! ---------
|
||||
set(LLVM_LIBRARY LLVMSelectionDAG LLVMCodeGen LLVMScalarOpts LLVMAnalysis LLVMArchive
|
||||
LLVMAsmParser LLVMAsmPrinter
|
||||
LLVMBitReader LLVMBitWriter
|
||||
LLVMDebugInfo LLVMExecutionEngine
|
||||
LLVMInstCombine LLVMInstrumentation
|
||||
LLVMInterpreter LLVMJIT
|
||||
LLVMLinker LLVMMC
|
||||
LLVMMCDisassembler LLVMMCJIT
|
||||
LLVMMCParser LLVMObject
|
||||
LLVMRuntimeDyld
|
||||
LLVMSupport
|
||||
LLVMTableGen LLVMTarget
|
||||
LLVMTransformUtils LLVMVectorize
|
||||
LLVMX86AsmParser LLVMX86AsmPrinter
|
||||
LLVMX86CodeGen LLVMX86Desc
|
||||
LLVMX86Disassembler LLVMX86Info
|
||||
LLVMX86Utils LLVMipa
|
||||
LLVMipo LLVMCore)
|
||||
# imagehelp is needed by LLVM 3.1 on MinGW, check lib\Support\Windows\Signals.inc
|
||||
list(APPEND PLATFORM_LINKLIBS -limagehlp)
|
||||
endif()
|
||||
|
||||
if(WITH_OPENCOLORIO)
|
||||
set(OPENCOLORIO ${LIBDIR}/opencolorio)
|
||||
set(OPENCOLORIO_INCLUDE_DIRS ${OPENCOLORIO}/include)
|
||||
set(OPENCOLORIO_LIBRARIES OpenColorIO)
|
||||
set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib)
|
||||
set(OPENCOLORIO_DEFINITIONS)
|
||||
endif()
|
||||
|
||||
if(WITH_SDL)
|
||||
set(SDL ${LIBDIR}/sdl)
|
||||
set(SDL_INCLUDE_DIR ${SDL}/include)
|
||||
set(SDL_LIBRARY SDL)
|
||||
set(SDL_LIBPATH ${SDL}/lib)
|
||||
endif()
|
||||
|
||||
if(WITH_OPENVDB)
|
||||
set(OPENVDB ${LIBDIR}/openvdb)
|
||||
set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include)
|
||||
set(OPENVDB_LIBRARIES openvdb ${TBB_LIBRARIES})
|
||||
set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib)
|
||||
set(OPENVDB_DEFINITIONS)
|
||||
endif()
|
||||
|
||||
if(WITH_ALEMBIC)
|
||||
# TODO(sergey): For until someone drops by and compiles libraries for
|
||||
# MinGW we allow users to compile their own Alembic library and use
|
||||
# that via find_package(),
|
||||
#
|
||||
# Once precompiled libraries are there we'll use hardcoded locations.
|
||||
find_package_wrapper(Alembic)
|
||||
if(WITH_ALEMBIC_HDF5)
|
||||
set(HDF5_ROOT_DIR ${LIBDIR}/hdf5)
|
||||
find_package_wrapper(HDF5)
|
||||
endif()
|
||||
if(NOT ALEMBIC_FOUND OR (WITH_ALEMBIC_HDF5 AND NOT HDF5_FOUND))
|
||||
set(WITH_ALEMBIC OFF)
|
||||
set(WITH_ALEMBIC_HDF5 OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(PLATFORM_LINKFLAGS "-Xlinker --stack=2097152")
|
||||
|
||||
## DISABLE - causes linking errors
|
||||
## for re-distribution, so users dont need mingw installed
|
||||
# set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -static-libgcc -static-libstdc++")
|
@@ -116,7 +116,6 @@ set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /NODEFAULTLIB:msvcrt.lib /NODEFAUL
|
||||
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /ignore:4049 /ignore:4217 /ignore:4221")
|
||||
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221")
|
||||
|
||||
# MSVC only, Mingw doesnt need
|
||||
if(CMAKE_CL_64)
|
||||
set(PLATFORM_LINKFLAGS "/MACHINE:X64 ${PLATFORM_LINKFLAGS}")
|
||||
else()
|
||||
@@ -453,32 +452,28 @@ if(WITH_MOD_CLOTH_ELTOPO)
|
||||
endif()
|
||||
|
||||
if(WITH_OPENSUBDIV OR WITH_CYCLES_OPENSUBDIV)
|
||||
set(OPENSUBDIV_INCLUDE_DIR ${LIBDIR}/opensubdiv/include)
|
||||
set(OPENSUBDIV_LIBPATH ${LIBDIR}/opensubdiv/lib)
|
||||
set(OPENSUBDIV_LIBRARIES optimized ${OPENSUBDIV_LIBPATH}/osdCPU.lib
|
||||
optimized ${OPENSUBDIV_LIBPATH}/osdGPU.lib
|
||||
debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib
|
||||
debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib
|
||||
)
|
||||
set(OPENSUBDIV_HAS_OPENMP TRUE)
|
||||
set(OPENSUBDIV_INCLUDE_DIR ${LIBDIR}/opensubdiv/include)
|
||||
set(OPENSUBDIV_LIBPATH ${LIBDIR}/opensubdiv/lib)
|
||||
set(OPENSUBDIV_LIBRARIES
|
||||
optimized ${OPENSUBDIV_LIBPATH}/osdCPU.lib
|
||||
optimized ${OPENSUBDIV_LIBPATH}/osdGPU.lib
|
||||
debug ${OPENSUBDIV_LIBPATH}/osdCPU_d.lib
|
||||
debug ${OPENSUBDIV_LIBPATH}/osdGPU_d.lib
|
||||
)
|
||||
set(OPENSUBDIV_HAS_OPENMP TRUE)
|
||||
set(OPENSUBDIV_HAS_TBB FALSE)
|
||||
set(OPENSUBDIV_HAS_OPENCL TRUE)
|
||||
set(OPENSUBDIV_HAS_CUDA FALSE)
|
||||
set(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK TRUE)
|
||||
set(OPENSUBDIV_HAS_GLSL_COMPUTE TRUE)
|
||||
windows_find_package(OpenSubdiv)
|
||||
windows_find_package(OpenSubdiv)
|
||||
endif()
|
||||
|
||||
if(WITH_SDL)
|
||||
set(SDL ${LIBDIR}/sdl)
|
||||
set(SDL_INCLUDE_DIR ${SDL}/include)
|
||||
set(SDL_LIBPATH ${SDL}/lib)
|
||||
# MinGW TODO: Update MinGW to SDL2
|
||||
if(NOT CMAKE_COMPILER_IS_GNUCC)
|
||||
set(SDL_LIBRARY SDL2)
|
||||
else()
|
||||
set(SDL_LIBRARY SDL)
|
||||
endif()
|
||||
set(SDL_LIBRARY SDL2)
|
||||
endif()
|
||||
|
||||
# Audio IO
|
||||
@@ -494,14 +489,14 @@ endif()
|
||||
# used in many places so include globally, like OpenGL
|
||||
blender_include_dirs_sys("${PTHREADS_INCLUDE_DIRS}")
|
||||
|
||||
#find signtool
|
||||
SET(ProgramFilesX86_NAME "ProgramFiles(x86)") #env dislikes the ( )
|
||||
#find signtool
|
||||
set(ProgramFilesX86_NAME "ProgramFiles(x86)") #env dislikes the ( )
|
||||
find_program(SIGNTOOL_EXE signtool
|
||||
HINTS
|
||||
"$ENV{${ProgramFilesX86_NAME}}/Windows Kits/10/bin/x86/"
|
||||
"$ENV{ProgramFiles}/Windows Kits/10/bin/x86/"
|
||||
"$ENV{${ProgramFilesX86_NAME}}/Windows Kits/8.1/bin/x86/"
|
||||
"$ENV{ProgramFiles}/Windows Kits/8.1/bin/x86/"
|
||||
"$ENV{${ProgramFilesX86_NAME}}/Windows Kits/8.0/bin/x86/"
|
||||
"$ENV{ProgramFiles}/Windows Kits/8.0/bin/x86/"
|
||||
HINTS
|
||||
"$ENV{${ProgramFilesX86_NAME}}/Windows Kits/10/bin/x86/"
|
||||
"$ENV{ProgramFiles}/Windows Kits/10/bin/x86/"
|
||||
"$ENV{${ProgramFilesX86_NAME}}/Windows Kits/8.1/bin/x86/"
|
||||
"$ENV{ProgramFiles}/Windows Kits/8.1/bin/x86/"
|
||||
"$ENV{${ProgramFilesX86_NAME}}/Windows Kits/8.0/bin/x86/"
|
||||
"$ENV{ProgramFiles}/Windows Kits/8.0/bin/x86/"
|
||||
)
|
||||
|
@@ -84,10 +84,8 @@ def init(cmake_path):
|
||||
|
||||
def source_list(path, filename_check=None):
|
||||
for dirpath, dirnames, filenames in os.walk(path):
|
||||
|
||||
# skip '.svn'
|
||||
if dirpath.startswith("."):
|
||||
continue
|
||||
# skip '.git'
|
||||
dirnames[:] = [d for d in dirnames if not d.startswith(".")]
|
||||
|
||||
for filename in filenames:
|
||||
filepath = join(dirpath, filename)
|
||||
@@ -145,7 +143,7 @@ def cmake_advanced_info():
|
||||
def create_eclipse_project():
|
||||
print("CMAKE_DIR %r" % CMAKE_DIR)
|
||||
if sys.platform == "win32":
|
||||
cmd = 'cmake "%s" -G"Eclipse CDT4 - MinGW Makefiles"' % CMAKE_DIR
|
||||
raise Exception("Error: win32 is not supported")
|
||||
else:
|
||||
if make_exe_basename.startswith(("make", "gmake")):
|
||||
cmd = 'cmake "%s" -G"Eclipse CDT4 - Unix Makefiles"' % CMAKE_DIR
|
||||
|
@@ -38,7 +38,7 @@ PROJECT_NAME = Blender
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = "V2.8x"
|
||||
PROJECT_NUMBER = "V2.79"
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
@@ -32,3 +32,62 @@ Module References
|
||||
-----------------
|
||||
|
||||
"""
|
||||
|
||||
import bpy
|
||||
|
||||
# This block can be automatically generated by UI translations addon, which also handles conversion with PO format.
|
||||
# See also https://wiki.blender.org/index.php/Dev:Doc/Process/Translate_Blender#Translating_non-official_addons
|
||||
# It can (should) also be put in a different, specific py file.
|
||||
|
||||
# ##### BEGIN AUTOGENERATED I18N SECTION #####
|
||||
# NOTE: You can safely move around this auto-generated block (with the begin/end markers!),
|
||||
# and edit the translations by hand.
|
||||
# Just carefully respect the format of the tuple!
|
||||
|
||||
# Tuple of tuples ((msgctxt, msgid), (sources, gen_comments), (lang, translation, (is_fuzzy, comments)), ...)
|
||||
translations_tuple = (
|
||||
(("*", ""),
|
||||
((), ()),
|
||||
("fr_FR", "Project-Id-Version: Copy Settings 0.1.5 (r0)\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: 2013-04-18 15:27:45.563524\nPO-Revision-Date: 2013-04-18 15:38+0100\nLast-Translator: Bastien Montagne <montagne29@wanadoo.fr>\nLanguage-Team: LANGUAGE <LL@li.org>\nLanguage: __POT__\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\n",
|
||||
(False,
|
||||
("Blender's translation file (po format).",
|
||||
"Copyright (C) 2013 The Blender Foundation.",
|
||||
"This file is distributed under the same license as the Blender package.",
|
||||
"FIRST AUTHOR <EMAIL@ADDRESS>, YEAR."))),
|
||||
),
|
||||
(("Operator", "Render: Copy Settings"),
|
||||
(("bpy.types.SCENE_OT_render_copy_settings",),
|
||||
()),
|
||||
("fr_FR", "Rendu : copier réglages",
|
||||
(False, ())),
|
||||
),
|
||||
(("*", "Copy render settings from current scene to others"),
|
||||
(("bpy.types.SCENE_OT_render_copy_settings",),
|
||||
()),
|
||||
("fr_FR", "Copier les réglages de rendu depuis la scène courante vers d’autres",
|
||||
(False, ())),
|
||||
),
|
||||
# ... etc, all messages from your addon.
|
||||
)
|
||||
|
||||
translations_dict = {}
|
||||
for msg in translations_tuple:
|
||||
key = msg[0]
|
||||
for lang, trans, (is_fuzzy, comments) in msg[2:]:
|
||||
if trans and not is_fuzzy:
|
||||
translations_dict.setdefault(lang, {})[key] = trans
|
||||
|
||||
# ##### END AUTOGENERATED I18N SECTION #####
|
||||
|
||||
# Define remaining addon (operators, UI...) here.
|
||||
|
||||
def register():
|
||||
# Usual operator/UI/etc. registration...
|
||||
|
||||
bpy.app.translations.register(__name__, translations_dict)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.app.translations.unregister(__name__)
|
||||
|
||||
# Usual operator/UI/etc. unregistration...
|
||||
|
@@ -2,13 +2,14 @@
|
||||
Modal Execution
|
||||
+++++++++++++++
|
||||
|
||||
This operator defines a :class:`Operator.modal` function which running,
|
||||
handling events until it returns ``{'FINISHED'}`` or ``{'CANCELLED'}``.
|
||||
This operator defines a :class:`Operator.modal` function that will keep being
|
||||
run to handle events until it returns ``{'FINISHED'}`` or ``{'CANCELLED'}``.
|
||||
|
||||
Grab, Rotate, Scale and Fly-Mode are examples of modal operators.
|
||||
They are especially useful for interactive tools,
|
||||
your operator can have its own state where keys toggle options as the operator
|
||||
runs.
|
||||
Modal operators run every time a new event is detected, such as a mouse click
|
||||
or key press. Conversely, when no new events are detected, the modal operator
|
||||
will not run. Modal operators are especially useful for interactive tools, an
|
||||
operator can have its own state where keys toggle options as the operator runs.
|
||||
Grab, Rotate, Scale, and Fly-Mode are examples of modal operators.
|
||||
|
||||
:class:`Operator.invoke` is used to initialize the operator as being by
|
||||
returning ``{'RUNNING_MODAL'}``, initializing the modal loop.
|
||||
|
@@ -47,4 +47,3 @@ Module to access application values that remain unchanged during runtime.
|
||||
True if the BGE has been built with physics support.
|
||||
|
||||
:type: bool
|
||||
|
||||
|
@@ -59,7 +59,7 @@ base class --- :class:`SCA_IActuator`
|
||||
|
||||
.. attribute:: mode
|
||||
|
||||
The operation mode of the actuator. Can be one of :ref:`these constants<shape-action-actuator>`.
|
||||
The operation mode of the actuator. Can be one of :ref:`these constants<action-actuator>`.
|
||||
|
||||
:type: integer
|
||||
|
||||
@@ -68,5 +68,3 @@ base class --- :class:`SCA_IActuator`
|
||||
The name of the property that is set to the current frame number.
|
||||
|
||||
:type: string
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,13 @@ GPU functions (gpu)
|
||||
|
||||
This module provides access to materials GLSL shaders.
|
||||
|
||||
Submodules:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
gpu.offscreen.rst
|
||||
|
||||
|
||||
Intro
|
||||
=====
|
||||
@@ -24,7 +31,6 @@ and in the game engine.
|
||||
Constants
|
||||
=========
|
||||
|
||||
|
||||
GLSL Data Type
|
||||
--------------
|
||||
|
||||
|
@@ -7,14 +7,17 @@
|
||||
|
||||
Submodules:
|
||||
|
||||
* :mod:`bmesh.ops`
|
||||
* :mod:`bmesh.types`
|
||||
* :mod:`bmesh.utils`
|
||||
* :mod:`bmesh.geometry`
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
bmesh.ops.rst
|
||||
bmesh.types.rst
|
||||
bmesh.utils.rst
|
||||
bmesh.geometry.rst
|
||||
|
||||
|
||||
Intro
|
||||
-----
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This API gives access the blenders internal mesh editing api, featuring geometry connectivity data and
|
||||
access to editing operations such as split, separate, collapse and dissolve.
|
||||
|
@@ -5,23 +5,25 @@
|
||||
Python API Overview
|
||||
*******************
|
||||
|
||||
This document is to give an understanding of how Python and Blender fit together,
|
||||
covering some of the functionality that isn't obvious from reading the API reference and example scripts.
|
||||
The purpose of this document is to explain how Python and Blender fit together,
|
||||
covering some of the functionality that may not be obvious from reading the API
|
||||
references and example scripts.
|
||||
|
||||
|
||||
Python in Blender
|
||||
=================
|
||||
|
||||
Blender embeds a Python interpreter which is started with Blender and stays active.
|
||||
This interpreter runs scripts to draw the user interface and is used for some of Blender's internal tools too.
|
||||
Blender has an embedded Python interpreter which is loaded when Blender is started and stays
|
||||
active while Blender is running. This interpreter runs scripts to draw the user interface
|
||||
and is used for some of Blender’s internal tools as well.
|
||||
|
||||
This is a typical Python environment so tutorials on how to write Python scripts
|
||||
will work running the scripts in Blender too.
|
||||
Blender provides the :mod:`bpy` module to the Python interpreter.
|
||||
This module can be imported in a script and gives access to Blender data, classes, and functions.
|
||||
Scripts that deal with Blender data will need to import this module.
|
||||
Blender's embedded interpreter provides a typical Python environment, so code from tutorials
|
||||
on how to write Python scripts can also be run with Blender’s interpreter. Blender provides its
|
||||
Python modules, such as :mod:`bpy` and :mod:`mathutils`, to the embedded interpreter so they can
|
||||
be imported into a script and give access to Blender's data, classes, and functions. Scripts that
|
||||
deal with Blender data will need to import the modules to work.
|
||||
|
||||
Here is a simple example of moving a vertex of the object named **Cube**:
|
||||
Here is a simple example which moves a vertex attached to an object named **Cube**:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -49,15 +51,17 @@ See the :ref:`directory layout docs <blender_manual:getting-started_installing-c
|
||||
Script Loading
|
||||
==============
|
||||
|
||||
This may seem obvious but it's important to note the difference
|
||||
between executing a script directly or importing it as a module.
|
||||
This may seem obvious, but it is important to note the difference between
|
||||
executing a script directly and importing a script as a module.
|
||||
|
||||
Scripts that extend Blender - define classes that exist beyond the scripts execution,
|
||||
this makes future access to these classes (to unregister for example)
|
||||
more difficult than importing as a module where class instance is kept
|
||||
in the module and can be accessed by importing that module later on.
|
||||
Extending Blender by executing a script directly means the classes that the script
|
||||
defines remain available inside Blender after the script finishes execution.
|
||||
Using scripts this way makes future access to their classes
|
||||
(to unregister them for example) more difficult compared to importing the scripts as modules.
|
||||
When a script is imported as a module, its class instances will remain
|
||||
inside the module and can be accessed later on by importing that module again.
|
||||
|
||||
For this reason it's preferable to only use directly execute scripts that don't extend Blender by registering classes.
|
||||
For this reason it is preferable to avoid directly executing scripts that extend Blender by registering classes.
|
||||
|
||||
|
||||
Here are some ways to run scripts directly in Blender.
|
||||
@@ -396,8 +400,8 @@ This works just as well for PropertyGroup subclasses you define yourself.
|
||||
Dynamic Defined-Classes (Advanced)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In some cases the specifier for data may not be in Blender,
|
||||
renderman shader definitions for example and it may be useful to define types and remove them on the fly.
|
||||
In some cases the specifier for data may not be in Blender, renderman shader definitions
|
||||
for example, and it may be useful to define them as types and remove them on the fly.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -420,7 +424,7 @@ renderman shader definitions for example and it may be useful to define types an
|
||||
This is an alternative syntax for class creation in Python, better suited to constructing classes dynamically.
|
||||
|
||||
|
||||
Calling these operators:
|
||||
To call the operators from the previous example:
|
||||
|
||||
>>> bpy.ops.object.operator_1()
|
||||
Hello World OBJECT_OT_operator_1
|
||||
|
@@ -1,635 +0,0 @@
|
||||
|
||||
Add-on Tutorial
|
||||
###############
|
||||
|
||||
************
|
||||
Introduction
|
||||
************
|
||||
|
||||
|
||||
Intended Audience
|
||||
=================
|
||||
|
||||
This tutorial is designed to help technical artists or developers learn to extend Blender.
|
||||
An understanding of the basics of Python is expected for those working through this tutorial.
|
||||
|
||||
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
Before going through the tutorial you should...
|
||||
|
||||
- Familiarity with the basics of working in Blender.
|
||||
- Know how to run a script in Blender's text editor (as documented in the quick-start)
|
||||
- Have an understanding of Python primitive types (int, boolean, string, list, tuple, dictionary, and set).
|
||||
- Be familiar with the concept of Python modules.
|
||||
- Basic understanding of classes (object orientation) in Python.
|
||||
|
||||
|
||||
Suggested reading before starting this tutorial.
|
||||
|
||||
- `Dive Into Python <http://getpython3.com/diveintopython3/index.html>`_ sections (1, 2, 3, 4, and 7).
|
||||
- :ref:`Blender API Quickstart <info_quickstart>`
|
||||
to help become familiar with Blender/Python basics.
|
||||
|
||||
|
||||
To best troubleshoot any error message Python prints while writing scripts you run blender with from a terminal,
|
||||
see :ref:`Use The Terminal <use_the_terminal>`.
|
||||
|
||||
|
||||
Documentation Links
|
||||
===================
|
||||
|
||||
While going through the tutorial you may want to look into our reference documentation.
|
||||
|
||||
- :ref:`Blender API Overview <info_overview>`. -
|
||||
*This document is rather detailed but helpful if you want to know more on a topic.*
|
||||
- :mod:`bpy.context` api reference. -
|
||||
*Handy to have a list of available items your script may operate on.*
|
||||
- :class:`bpy.types.Operator`. -
|
||||
*The following add-ons define operators, these docs give details and more examples of operators.*
|
||||
|
||||
|
||||
*******
|
||||
Add-ons
|
||||
*******
|
||||
|
||||
What is an Add-on?
|
||||
==================
|
||||
|
||||
An add-on is simply a Python module with some additional requirements so Blender can display it in a list with useful
|
||||
information.
|
||||
|
||||
To give an example, here is the simplest possible add-on.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
bl_info = {"name": "My Test Add-on", "category": "Object"}
|
||||
def register():
|
||||
print("Hello World")
|
||||
def unregister():
|
||||
print("Goodbye World")
|
||||
|
||||
|
||||
- ``bl_info`` is a dictionary containing add-on metadata such as the title,
|
||||
version and author to be displayed in the user preferences add-on list.
|
||||
- ``register`` is a function which only runs when enabling the add-on,
|
||||
this means the module can be loaded without activating the add-on.
|
||||
- ``unregister`` is a function to unload anything setup by ``register``, this is called when the add-on is disabled.
|
||||
|
||||
|
||||
Notice this add-on does not do anything related to Blender, (the :mod:`bpy` module is not imported for example).
|
||||
|
||||
This is a contrived example of an add-on that serves to illustrate the point
|
||||
that the base requirements of an add-on are simple.
|
||||
|
||||
An add-on will typically register operators, panels, menu items etc, but its worth noting that _any_ script can do this,
|
||||
when executed from the text editor or even the interactive console - there is nothing inherently different about an
|
||||
add-on that allows it to integrate with Blender, such functionality is just provided by the :mod:`bpy` module for any
|
||||
script to access.
|
||||
|
||||
So an add-on is just a way to encapsulate a Python module in a way a user can easily utilize.
|
||||
|
||||
.. note::
|
||||
|
||||
Running this script within the text editor won't print anything,
|
||||
to see the output it must be installed through the user preferences.
|
||||
Messages will be printed when enabling and disabling.
|
||||
|
||||
|
||||
Your First Add-on
|
||||
=================
|
||||
|
||||
The simplest possible add-on above is useful as an example but not much else.
|
||||
This next add-on is simple but shows how to integrate a script into Blender using an ``Operator``
|
||||
which is the typical way to define a tool accessed from menus, buttons and keyboard shortcuts.
|
||||
|
||||
For the first example we will make a script that simply moves all objects in a scene.
|
||||
|
||||
|
||||
Write The Script
|
||||
----------------
|
||||
|
||||
Add the following script to the text editor in Blender.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import bpy
|
||||
|
||||
scene = bpy.context.scene
|
||||
for obj in scene.objects:
|
||||
obj.location.x += 1.0
|
||||
|
||||
|
||||
Click the :ref:`Run Script button <blender_manual:editors-text-run-script>`,
|
||||
all objects in the active scene are moved by 1.0 Blender unit.
|
||||
|
||||
|
||||
Write the Add-on (Simple)
|
||||
-------------------------
|
||||
|
||||
This add-on takes the body of the script above, and adds them to an operator's ``execute()`` function.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
bl_info = {
|
||||
"name": "Move X Axis",
|
||||
"category": "Object",
|
||||
}
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
class ObjectMoveX(bpy.types.Operator):
|
||||
"""My Object Moving Script""" # blender will use this as a tooltip for menu items and buttons.
|
||||
bl_idname = "object.move_x" # unique identifier for buttons and menu items to reference.
|
||||
bl_label = "Move X by One" # display name in the interface.
|
||||
bl_options = {'REGISTER', 'UNDO'} # enable undo for the operator.
|
||||
|
||||
def execute(self, context): # execute() is called by blender when running the operator.
|
||||
|
||||
# The original script
|
||||
scene = context.scene
|
||||
for obj in scene.objects:
|
||||
obj.location.x += 1.0
|
||||
|
||||
return {'FINISHED'} # this lets blender know the operator finished successfully.
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(ObjectMoveX)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(ObjectMoveX)
|
||||
|
||||
|
||||
# This allows you to run the script directly from blenders text editor
|
||||
# to test the add-on without having to install it.
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
``bl_info`` is split across multiple lines, this is just a style convention used to more easily add items.
|
||||
|
||||
.. note::
|
||||
|
||||
Rather than using ``bpy.context.scene``, we use the ``context.scene`` argument passed to ``execute()``.
|
||||
In most cases these will be the same however in some cases operators will be passed a custom context
|
||||
so script authors should prefer the ``context`` argument passed to operators.
|
||||
|
||||
To test the script you can copy and paste this into Blender text editor and run it, this will execute the script
|
||||
directly and call register immediately.
|
||||
|
||||
However running the script wont move any objects, for this you need to execute the newly registered operator.
|
||||
|
||||
.. image:: spacebar.png
|
||||
:width: 924px
|
||||
:align: center
|
||||
:height: 574px
|
||||
:alt: Spacebar
|
||||
|
||||
Do this by pressing :kbd:`Spacebar` to bring up the operator search dialog and type in
|
||||
"Move X by One" (the ``bl_label``), then :kbd:`Enter`.
|
||||
|
||||
|
||||
|
||||
The objects should move as before.
|
||||
|
||||
*Keep this add-on open in Blender for the next step - Installing.*
|
||||
|
||||
|
||||
Install The Add-on
|
||||
------------------
|
||||
|
||||
Once you have your add-on within in Blender's text editor,
|
||||
you will want to be able to install it so it can be enabled in the user preferences to load on startup.
|
||||
|
||||
Even though the add-on above is a test, lets go through the steps anyway so you know how to do it for later.
|
||||
|
||||
To install the Blender text as an add-on you will first have to save it to disk, take care to obey the naming
|
||||
restrictions that apply to Python modules and end with a ``.py`` extension.
|
||||
|
||||
Once the file is on disk, you can install it as you would for an add-on downloaded online.
|
||||
|
||||
Open the user :menuselection:`File --> User Preferences`,
|
||||
Select the *Add-on* section, press *Install Add-on...* and select the file.
|
||||
|
||||
Now the add-on will be listed and you can enable it by pressing the check-box,
|
||||
if you want it to be enabled on restart, press *Save as Default*.
|
||||
|
||||
.. note::
|
||||
|
||||
The destination of the add-on depends on your Blender configuration.
|
||||
When installing an add-on the source and destination path are printed in the console.
|
||||
You can also find add-on path locations by running this in the Python console.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import addon_utils
|
||||
print(addon_utils.paths())
|
||||
|
||||
More is written on this topic here:
|
||||
:ref:`Directory Layout <blender_manual:getting-started_installing-config-directories>`.
|
||||
|
||||
|
||||
Your Second Add-on
|
||||
==================
|
||||
|
||||
For our second add-on, we will focus on object instancing - this is - to make linked copies of an object in a
|
||||
similar way to what you may have seen with the array modifier.
|
||||
|
||||
|
||||
Write The Script
|
||||
----------------
|
||||
|
||||
As before, first we will start with a script, develop it, then convert into an add-on.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import bpy
|
||||
from bpy import context
|
||||
|
||||
# Get the current scene
|
||||
scene = context.scene
|
||||
|
||||
# Get the 3D cursor
|
||||
cursor = scene.cursor_location
|
||||
|
||||
# Get the active object (assume we have one)
|
||||
obj = scene.objects.active
|
||||
|
||||
# Now make a copy of the object
|
||||
obj_new = obj.copy()
|
||||
|
||||
# The object won't automatically get into a new scene
|
||||
scene.objects.link(obj_new)
|
||||
|
||||
# Now we can place the object
|
||||
obj_new.location = cursor
|
||||
|
||||
|
||||
Now try copy this script into Blender and run it on the default cube.
|
||||
Make sure you click to move the 3D cursor before running as the duplicate will appear at the cursor's location.
|
||||
|
||||
|
||||
... go off and test ...
|
||||
|
||||
|
||||
After running, notice that when you go into edit-mode to change the cube - all of the copies change,
|
||||
in Blender this is known as *Linked-Duplicates*.
|
||||
|
||||
|
||||
Next, we're going to do this in a loop, to make an array of objects between the active object and the cursor.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import bpy
|
||||
from bpy import context
|
||||
|
||||
scene = context.scene
|
||||
cursor = scene.cursor_location
|
||||
obj = scene.objects.active
|
||||
|
||||
# Use a fixed value for now, eventually make this user adjustable
|
||||
total = 10
|
||||
|
||||
# Add 'total' objects into the scene
|
||||
for i in range(total):
|
||||
obj_new = obj.copy()
|
||||
scene.objects.link(obj_new)
|
||||
|
||||
# Now place the object in between the cursor
|
||||
# and the active object based on 'i'
|
||||
factor = i / total
|
||||
obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
|
||||
|
||||
|
||||
Try run this script with with the active object and the cursor spaced apart to see the result.
|
||||
|
||||
With this script you'll notice we're doing some math with the object location and cursor, this works because both are
|
||||
3D :class:`mathutils.Vector` instances, a convenient class provided by the :mod:`mathutils` module and
|
||||
allows vectors to be multiplied by numbers and matrices.
|
||||
|
||||
If you are interested in this area, read into :class:`mathutils.Vector` - there are many handy utility functions
|
||||
such as getting the angle between vectors, cross product, dot products
|
||||
as well as more advanced functions in :mod:`mathutils.geometry` such as Bézier Spline interpolation and
|
||||
ray-triangle intersection.
|
||||
|
||||
For now we will focus on making this script an add-on, but its good to know that this 3D math module is available and
|
||||
can help you with more advanced functionality later on.
|
||||
|
||||
|
||||
Write the Add-on
|
||||
----------------
|
||||
|
||||
The first step is to convert the script as-is into an add-on.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
bl_info = {
|
||||
"name": "Cursor Array",
|
||||
"category": "Object",
|
||||
}
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
class ObjectCursorArray(bpy.types.Operator):
|
||||
"""Object Cursor Array"""
|
||||
bl_idname = "object.cursor_array"
|
||||
bl_label = "Cursor Array"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def execute(self, context):
|
||||
scene = context.scene
|
||||
cursor = scene.cursor_location
|
||||
obj = scene.objects.active
|
||||
|
||||
total = 10
|
||||
|
||||
for i in range(total):
|
||||
obj_new = obj.copy()
|
||||
scene.objects.link(obj_new)
|
||||
|
||||
factor = i / total
|
||||
obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(ObjectCursorArray)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(ObjectCursorArray)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
||||
|
||||
Everything here has been covered in the previous steps, you may want to try run the add-on still
|
||||
and consider what could be done to make it more useful.
|
||||
|
||||
|
||||
... go off and test ...
|
||||
|
||||
|
||||
The two of the most obvious missing things are - having the total fixed at 10, and having to access the operator from
|
||||
space-bar is not very convenient.
|
||||
|
||||
Both these additions are explained next, with the final script afterwards.
|
||||
|
||||
|
||||
Operator Property
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
There are a variety of property types that are used for tool settings, common property types include:
|
||||
int, float, vector, color, boolean and string.
|
||||
|
||||
These properties are handled differently to typical Python class attributes
|
||||
because Blender needs to be display them in the interface,
|
||||
store their settings in key-maps and keep settings for re-use.
|
||||
|
||||
While this is handled in a fairly Pythonic way, be mindful that you are in fact defining tool settings that
|
||||
are loaded into Blender and accessed by other parts of Blender, outside of Python.
|
||||
|
||||
|
||||
To get rid of the literal 10 for `total`, we'll us an operator property.
|
||||
Operator properties are defined via bpy.props module, this is added to the class body.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# moved assignment from execute() to the body of the class...
|
||||
total = bpy.props.IntProperty(name="Steps", default=2, min=1, max=100)
|
||||
|
||||
# and this is accessed on the class
|
||||
# instance within the execute() function as...
|
||||
self.total
|
||||
|
||||
|
||||
These properties from :mod:`bpy.props` are handled specially by Blender when the class is registered
|
||||
so they display as buttons in the user interface.
|
||||
There are many arguments you can pass to properties to set limits, change the default and display a tooltip.
|
||||
|
||||
.. seealso:: :mod:`bpy.props.IntProperty`
|
||||
|
||||
This document doesn't go into details about using other property types,
|
||||
however the link above includes examples of more advanced property usage.
|
||||
|
||||
|
||||
Menu Item
|
||||
^^^^^^^^^
|
||||
|
||||
Add-ons can add to the user interface of existing panels, headers and menus defined in Python.
|
||||
|
||||
For this example we'll add to an existing menu.
|
||||
|
||||
.. image:: menu_id.png
|
||||
:width: 334px
|
||||
:align: center
|
||||
:height: 128px
|
||||
:alt: Menu Identifier
|
||||
|
||||
To find the identifier of a menu you can hover your mouse over the menu item and the identifier is displayed.
|
||||
|
||||
The method used for adding a menu item is to append a draw function into an existing class.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(ObjectCursorArray.bl_idname)
|
||||
|
||||
def register():
|
||||
bpy.types.VIEW3D_MT_object.append(menu_func)
|
||||
|
||||
|
||||
For docs on extending menus see: :doc:`bpy.types.Menu`.
|
||||
|
||||
|
||||
Keymap
|
||||
^^^^^^
|
||||
|
||||
In Blender, add-ons have their own keymaps so as not to interfere with Blenders built in key-maps.
|
||||
|
||||
In the example below, a new object-mode :class:`bpy.types.KeyMap` is added,
|
||||
then a :class:`bpy.types.KeyMapItem` is added to the key-map which references our newly added operator,
|
||||
using :kbd:`Ctrl-Shift-Space` as the key shortcut to activate it.
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# store keymaps here to access after registration
|
||||
addon_keymaps = []
|
||||
|
||||
def register():
|
||||
|
||||
# handle the keymap
|
||||
wm = bpy.context.window_manager
|
||||
km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
|
||||
|
||||
kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)
|
||||
kmi.properties.total = 4
|
||||
|
||||
addon_keymaps.append((km, kmi))
|
||||
|
||||
|
||||
def unregister():
|
||||
|
||||
# handle the keymap
|
||||
for km, kmi in addon_keymaps:
|
||||
km.keymap_items.remove(kmi)
|
||||
addon_keymaps.clear()
|
||||
|
||||
|
||||
Notice how the key-map item can have a different ``total`` setting then the default set by the operator,
|
||||
this allows you to have multiple keys accessing the same operator with different settings.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
While :kbd:`Ctrl-Shift-Space` isn't a default Blender key shortcut, its hard to make sure add-ons won't
|
||||
overwrite each others keymaps, At least take care when assigning keys that they don't
|
||||
conflict with important functionality within Blender.
|
||||
|
||||
For API documentation on the functions listed above, see:
|
||||
:class:`bpy.types.KeyMaps.new`,
|
||||
:class:`bpy.types.KeyMap`,
|
||||
:class:`bpy.types.KeyMapItems.new`,
|
||||
:class:`bpy.types.KeyMapItem`.
|
||||
|
||||
|
||||
Bringing it all together
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
bl_info = {
|
||||
"name": "Cursor Array",
|
||||
"category": "Object",
|
||||
}
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
class ObjectCursorArray(bpy.types.Operator):
|
||||
"""Object Cursor Array"""
|
||||
bl_idname = "object.cursor_array"
|
||||
bl_label = "Cursor Array"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
total = bpy.props.IntProperty(name="Steps", default=2, min=1, max=100)
|
||||
|
||||
def execute(self, context):
|
||||
scene = context.scene
|
||||
cursor = scene.cursor_location
|
||||
obj = scene.objects.active
|
||||
|
||||
for i in range(self.total):
|
||||
obj_new = obj.copy()
|
||||
scene.objects.link(obj_new)
|
||||
|
||||
factor = i / self.total
|
||||
obj_new.location = (obj.location * factor) + (cursor * (1.0 - factor))
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(ObjectCursorArray.bl_idname)
|
||||
|
||||
# store keymaps here to access after registration
|
||||
addon_keymaps = []
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(ObjectCursorArray)
|
||||
bpy.types.VIEW3D_MT_object.append(menu_func)
|
||||
|
||||
# handle the keymap
|
||||
wm = bpy.context.window_manager
|
||||
# Note that in background mode (no GUI available), keyconfigs are not available either, so we have to check this
|
||||
# to avoid nasty errors in background case.
|
||||
kc = wm.keyconfigs.addon
|
||||
if kc:
|
||||
km = wm.keyconfigs.addon.keymaps.new(name='Object Mode', space_type='EMPTY')
|
||||
kmi = km.keymap_items.new(ObjectCursorArray.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)
|
||||
kmi.properties.total = 4
|
||||
addon_keymaps.append((km, kmi))
|
||||
|
||||
def unregister():
|
||||
# Note: when unregistering, it's usually good practice to do it in reverse order you registered.
|
||||
# Can avoid strange issues like keymap still referring to operators already unregistered...
|
||||
# handle the keymap
|
||||
for km, kmi in addon_keymaps:
|
||||
km.keymap_items.remove(kmi)
|
||||
addon_keymaps.clear()
|
||||
|
||||
bpy.utils.unregister_class(ObjectCursorArray)
|
||||
bpy.types.VIEW3D_MT_object.remove(menu_func)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
||||
.. image:: in_menu.png
|
||||
:width: 591px
|
||||
:align: center
|
||||
:height: 649px
|
||||
:alt: In the menu
|
||||
|
||||
Run the script (or save it and add it through the Preferences like before) and it will appear in the menu.
|
||||
|
||||
.. image:: op_prop.png
|
||||
:width: 669px
|
||||
:align: center
|
||||
:height: 644px
|
||||
:alt: Operator Property
|
||||
|
||||
After selecting it from the menu, you can choose how many instance of the cube you want created.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
Directly executing the script multiple times will add the menu each time too.
|
||||
While not useful behavior, theres nothing to worry about since add-ons won't register them selves multiple
|
||||
times when enabled through the user preferences.
|
||||
|
||||
|
||||
Conclusions
|
||||
===========
|
||||
|
||||
Add-ons can encapsulate certain functionality neatly for writing tools to improve your work-flow or for writing utilities
|
||||
for others to use.
|
||||
|
||||
While there are limits to what Python can do within Blender, there is certainly a lot that can be achieved without
|
||||
having to dive into Blender's C/C++ code.
|
||||
|
||||
The example given in the tutorial is limited, but shows the Blender API used for common tasks that you can expand on
|
||||
to write your own tools.
|
||||
|
||||
|
||||
Further Reading
|
||||
---------------
|
||||
|
||||
Blender comes commented templates which are accessible from the text editor header, if you have specific areas
|
||||
you want to see example code for, this is a good place to start.
|
||||
|
||||
|
||||
Here are some sites you might like to check on after completing this tutorial.
|
||||
|
||||
- :ref:`Blender/Python API Overview <info_overview>` -
|
||||
*For more background details on Blender/Python integration.*
|
||||
- `How to Think Like a Computer Scientist <http://interactivepython.org/courselib/static/thinkcspy/index.html>`_ -
|
||||
*Great info for those who are still learning Python.*
|
||||
- `Blender Development (Wiki) <https://wiki.blender.org/index.php/Dev:Contents>`_ -
|
||||
*Blender Development, general information and helpful links.*
|
||||
- `Blender Artists (Coding Section) <https://blenderartists.org/forum/forumdisplay.php?47-Coding>`_ -
|
||||
*forum where people ask Python development questions*
|
||||
|
@@ -22,7 +22,7 @@
|
||||
# 'bmesh_opdefines.c' in order to avoid having to add a lot of introspection
|
||||
# data access into the api.
|
||||
#
|
||||
# The script is stupid becase it makes assumptions about formatting...
|
||||
# The script is stupid because it makes assumptions about formatting...
|
||||
# that each arg has its own line, that comments above or directly after will be __doc__ etc...
|
||||
#
|
||||
# We may want to replace this script with something else one day but for now its good enough.
|
||||
|
@@ -341,6 +341,8 @@ EXTRA_SOURCE_FILES = (
|
||||
"../examples/bge.texture.py",
|
||||
"../examples/bmesh.ops.1.py",
|
||||
"../examples/bpy.app.translations.py",
|
||||
"../static/favicon.ico",
|
||||
"../static/blender_logo.svg",
|
||||
)
|
||||
|
||||
|
||||
@@ -362,8 +364,6 @@ INFO_DOCS = (
|
||||
"Blender/Python Quickstart: new to Blender/scripting and want to get your feet wet?"),
|
||||
("info_overview.rst",
|
||||
"Blender/Python API Overview: a more complete explanation of Python integration"),
|
||||
("info_tutorial_addon.rst",
|
||||
"Blender/Python Add-on Tutorial: a step by step guide on how to write an add-on from scratch"),
|
||||
("info_api_reference.rst",
|
||||
"Blender/Python API Reference Usage: examples of how to use the API reference docs"),
|
||||
("info_best_practice.rst",
|
||||
@@ -1613,10 +1613,8 @@ def pyrna2sphinx(basepath):
|
||||
else:
|
||||
url_base = API_BASEURL
|
||||
|
||||
fw(" :file: `%s <%s/%s>`_:%d\n\n" % (location[0],
|
||||
url_base,
|
||||
location[0],
|
||||
location[1]))
|
||||
fw(" :file: `%s\\:%d <%s/%s$%d>`_\n\n" %
|
||||
(location[0], location[1], url_base, location[0], location[1]))
|
||||
|
||||
file.close()
|
||||
|
||||
@@ -1641,19 +1639,24 @@ def write_sphinx_conf_py(basepath):
|
||||
fw("version = '%s - API'\n" % BLENDER_VERSION_DOTS)
|
||||
fw("release = '%s - API'\n" % BLENDER_VERSION_DOTS)
|
||||
|
||||
# Quiet file not in table-of-contents warnings.
|
||||
fw("exclude_patterns = [\n")
|
||||
fw(" 'include__bmesh.rst',\n")
|
||||
fw("]\n\n")
|
||||
|
||||
if ARGS.sphinx_theme != 'default':
|
||||
fw("html_theme = '%s'\n" % ARGS.sphinx_theme)
|
||||
|
||||
if ARGS.sphinx_theme == "blender-org":
|
||||
fw("html_theme_path = ['../']\n")
|
||||
# copied with the theme, exclude else we get an error [T28873]
|
||||
fw("html_favicon = 'favicon.ico'\n") # in <theme>/static/
|
||||
|
||||
# not helpful since the source is generated, adds to upload size.
|
||||
fw("html_copy_source = False\n")
|
||||
fw("html_show_sphinx = False\n")
|
||||
fw("html_split_index = True\n")
|
||||
fw("\n")
|
||||
fw("html_extra_path = ['__/static/favicon.ico', '__/static/blender_logo.svg']\n")
|
||||
fw("html_favicon = '__/static/favicon.ico'\n")
|
||||
fw("html_logo = '__/static/blender_logo.svg'\n\n")
|
||||
|
||||
# needed for latex, pdf gen
|
||||
fw("latex_elements = {\n")
|
||||
@@ -1661,6 +1664,24 @@ def write_sphinx_conf_py(basepath):
|
||||
fw("}\n\n")
|
||||
|
||||
fw("latex_documents = [ ('contents', 'contents.tex', 'Blender Index', 'Blender Foundation', 'manual'), ]\n")
|
||||
|
||||
# Workaround for useless links leading to compile errors
|
||||
# See https://github.com/sphinx-doc/sphinx/issues/3866
|
||||
fw(r"""
|
||||
from sphinx.domains.python import PythonDomain
|
||||
|
||||
class PatchedPythonDomain(PythonDomain):
|
||||
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
|
||||
if 'refspecific' in node:
|
||||
del node['refspecific']
|
||||
return super(PatchedPythonDomain, self).resolve_xref(
|
||||
env, fromdocname, builder, typ, target, node, contnode)
|
||||
|
||||
def setup(sphinx):
|
||||
sphinx.override_domain(PatchedPythonDomain)
|
||||
""")
|
||||
# end workaround
|
||||
|
||||
file.close()
|
||||
|
||||
|
||||
@@ -1715,8 +1736,6 @@ def write_rst_contents(basepath):
|
||||
"bpy.utils.previews",
|
||||
"bpy.path",
|
||||
"bpy.app",
|
||||
"bpy.app.handlers",
|
||||
"bpy.app.translations",
|
||||
|
||||
# C modules
|
||||
"bpy.props",
|
||||
@@ -1731,19 +1750,9 @@ def write_rst_contents(basepath):
|
||||
fw(" :maxdepth: 1\n\n")
|
||||
|
||||
standalone_modules = (
|
||||
# mathutils
|
||||
"mathutils",
|
||||
"mathutils.geometry",
|
||||
"mathutils.bvhtree", "mathutils.kdtree",
|
||||
"mathutils.interpolate",
|
||||
"mathutils.noise",
|
||||
# misc
|
||||
"freestyle", "bgl", "blf",
|
||||
"gpu", "gpu.offscreen",
|
||||
"aud", "bpy_extras",
|
||||
"idprop.types",
|
||||
# bmesh, submodules are in own page
|
||||
"bmesh",
|
||||
# submodules are added in parent page
|
||||
"mathutils", "freestyle", "bgl", "blf", "gpu",
|
||||
"aud", "bpy_extras", "idprop.types", "bmesh",
|
||||
)
|
||||
|
||||
for mod in standalone_modules:
|
||||
|
116
doc/python_api/static/blender_logo.svg
Normal file
116
doc/python_api/static/blender_logo.svg
Normal file
@@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 55.032989 15.935012"
|
||||
height="60.226818"
|
||||
width="207.9987">
|
||||
<defs
|
||||
id="defs2">
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3020">
|
||||
<path
|
||||
style="stroke-width:1.06666672"
|
||||
d="M 0,0 H 211.2 V 61.866667 H 0 Z"
|
||||
id="path3022" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3020-8">
|
||||
<path
|
||||
style="stroke-width:1.06666672"
|
||||
d="M 0,0 H 211.2 V 61.866667 H 0 Z"
|
||||
id="path3022-1" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Blender Logo</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:source>https://www.blender.org/about/logo/</dc:source>
|
||||
<cc:license
|
||||
rdf:resource="(c) Blender Foundation" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(42.023693,-77.734934)"
|
||||
id="layer1">
|
||||
<g
|
||||
transform="matrix(0.26259939,0,0,-0.26259939,-42.237694,93.888967)"
|
||||
id="g3012"
|
||||
style="stroke-width:7.2904439">
|
||||
<g
|
||||
id="g3014"
|
||||
style="stroke-width:7.2904439" />
|
||||
<g
|
||||
id="g3016"
|
||||
style="stroke-width:7.2904439">
|
||||
<g
|
||||
clip-path="url(#clipPath3020-8)"
|
||||
id="g3018"
|
||||
style="stroke-width:7.2904439">
|
||||
<path
|
||||
id="path3024"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
|
||||
d="m 192.54827,44.510933 c 0,0 -125.158403,0 -128.688003,0 -0.07893,0.06187 -0.1504,0.1344 -0.2272,0.193067 -0.01813,0.0192 -18.9312,14.548267 -19.5008,14.986667 -0.032,0.0256 -0.06507,0.04907 -0.06507,0.04907 -3.029333,2.321067 -7.531733,2.369067 -10.721067,0.133334 -1.9968,-1.396267 -3.194666,-3.508267 -3.285333,-5.792 -0.0021,-0.09173 -0.0064,-0.1824 -0.0064,-0.2752 0,-1.185067 0.314667,-2.3296 0.8832,-3.357867 -5.857067,-0.0053 -11.746133,-0.0128 -11.746133,-0.0128 -4.3936,-0.0021 -8.3648,-2.965333 -9.2725337,-6.8928 C 9.7898667,42.9792 9.7248,42.411733 9.7248,41.8496 c 0,-1.643733 0.546133,-3.236267 1.5808,-4.542933 1.162667,-1.463467 2.842667,-2.448 4.7584,-2.832 C 10.530133,30.2272 5.0016,25.984 4.9973333,25.979733 4.9578667,25.949867 4.9248,25.924267 4.8970667,25.905067 c -2.2176,-1.703467 -3.68,-4.1728 -4.0106667,-6.770134 -0.0490667,-0.381866 -0.0714667,-0.7584 -0.0714667,-1.133866 0,-1.870934 0.5962667,-3.650134 1.7301334,-5.102934 1.3781333,-1.764266 3.4144,-2.884266 5.7322666,-3.147733 2.6549337,-0.3072 5.4495997,0.542933 7.6607997,2.330667 0.01493,0.01173 2.753067,2.256 5.639467,4.6176 1.060267,-2.555734 2.545067,-4.926934 4.465067,-7.0453337 2.4704,-2.7306666 5.473066,-4.8864 8.919466,-6.4128 C 38.5856,1.6352 42.466133,0.82453333 46.501333,0.83413333 50.5376,0.8416 54.417067,1.6629333 58.0352,3.2768 c 3.453867,1.5466667 6.449067,3.7109333 8.910933,6.4352 0.360534,0.4032 0.693334,0.8288 1.0272,1.2544 4.885334,0 124.574937,0 124.574937,0 9.84,0 17.8368,7.5232 17.8368,16.7712 0,9.248 -7.9968,16.773333 -17.8368,16.773333" />
|
||||
<path
|
||||
id="path3026"
|
||||
style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
|
||||
d="m 38.538667,28.497067 c 0.113066,2.016 1.101866,3.793066 2.590933,5.0528 1.4624,1.237333 3.428267,1.9936 5.575467,1.9936 2.144,0 4.110933,-0.756267 5.572266,-1.9936 1.490134,-1.259734 2.4768,-3.0368 2.590934,-5.050667 0.113066,-2.0736 -0.718934,-3.997867 -2.181334,-5.425067 C 51.1968,21.6224 49.0784,20.7104 46.705067,20.7104 c -2.3744,0 -4.497067,0.912 -5.9872,2.363733 -1.461334,1.4272 -2.292267,3.351467 -2.1792,5.422934" />
|
||||
<path
|
||||
id="path3028"
|
||||
style="fill:#f5792a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
|
||||
d="m 25.536,24.421333 c 0.01387,-0.7904 0.2656,-2.3232 0.6432,-3.521066 C 26.9728,18.3648 28.318933,16.0192 30.193067,13.950933 32.1152,11.8272 34.482133,10.119467 37.216,8.9088 c 2.872533,-1.2736 5.986133,-1.9210667 9.220267,-1.9157333 3.229866,0.00427 6.3424,0.6656 9.216,1.9477333 2.733866,1.2224 5.098666,2.9376 7.018666,5.063467 1.870934,2.074666 3.216,4.424533 4.010667,6.96 0.401067,1.282133 0.6528,2.581333 0.754133,3.886933 0.100267,1.285333 0.0576,2.571733 -0.1248,3.858133 -0.356266,2.507734 -1.223466,4.858667 -2.557866,7.002667 -1.2224,1.970133 -2.7968,3.696 -4.6688,5.147733 l 0.0053,0.0021 -18.8928,14.506666 c -0.016,0.0128 -0.02987,0.02667 -0.048,0.03733 -1.240533,0.952533 -3.3248,0.948266 -4.686933,-0.0053 -1.3792,-0.9632 -1.536,-2.557866 -0.3104,-3.5648 l -0.0043,-0.0043 7.8784,-6.407467 -24.016,-0.02667 c -0.01173,0 -0.0224,0 -0.032,0 -1.985067,-0.0011 -3.893333,-1.303466 -4.269867,-2.9504 -0.389333,-1.6768 0.958934,-3.067733 3.022934,-3.074133 l -0.0021,-0.0075 L 30.900267,39.3888 9.1786667,22.715733 c -0.026667,-0.02133 -0.0576,-0.0416 -0.0832,-0.06293 -2.0490667,-1.568 -2.7104,-4.178133 -1.4197334,-5.828267 1.3088,-1.68 4.0949337,-1.6832 6.1653337,-0.0096 L 25.696,26.516267 c 0,0 -0.173867,-1.3088 -0.16,-2.094934 z M 56,20.034133 c -2.443733,-2.488533 -5.8624,-3.899733 -9.563733,-3.9072 -3.7056,-0.0064 -7.124267,1.393067 -9.568,3.877334 -1.1936,1.210666 -2.0704,2.602666 -2.6112,4.087466 -0.529067,1.457067 -0.736,3.0048 -0.599467,4.5664 0.130133,1.527467 0.583467,2.9824 1.309867,4.3008 0.712533,1.293867 1.6928,2.465067 2.9056,3.454934 2.373333,1.934933 5.396266,2.981333 8.558933,2.9856 3.1648,0.0053 6.1856,-1.0336 8.561067,-2.961067 1.2096,-0.9856 2.190933,-2.151467 2.903466,-3.445333 0.728534,-1.316267 1.179734,-2.765867 1.314134,-4.2976 C 59.344,27.136 59.138133,25.5904 58.609067,24.1312 58.0672,22.6432 57.1936,21.2512 56,20.034133" />
|
||||
<path
|
||||
id="path3030"
|
||||
style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
|
||||
d="m 167.96587,28.529067 c 0.1824,2.0352 1.75466,3.325866 4.15786,3.325866 2.4064,0 3.97974,-1.290666 4.16214,-3.325866 z M 176.0384,23.504 c -0.61547,-1.508267 -2.06507,-2.401067 -4.03627,-2.401067 -2.46613,0 -4.12693,1.540267 -4.1952,3.9744 h 14.18347 c 0,0.251734 0,0.462934 0,0.715734 0,6.094933 -3.57653,9.518933 -9.98827,9.518933 -6.22506,0 -9.98826,-3.457067 -9.98826,-8.878933 0,-5.454934 3.82293,-8.9056 9.98826,-8.9056 3.70134,0 6.5696,1.2672 8.33814,3.4976 L 176.0384,23.504" />
|
||||
<path
|
||||
id="path3032"
|
||||
style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
|
||||
d="m 105.0336,28.519467 c 0.18667,2.036266 1.76,3.326933 4.16533,3.326933 2.40214,0 3.97547,-1.290667 4.15894,-3.326933 z m 8.07787,-5.025067 c -0.61547,-1.512533 -2.06614,-2.404267 -4.03947,-2.404267 -2.464,0 -4.12907,1.544534 -4.19413,3.9776 h 14.18026 c 0,0.2496 0,0.4608 0,0.712534 0,6.098133 -3.57546,9.524266 -9.98613,9.524266 -6.22933,0 -9.986133,-3.458133 -9.986133,-8.88 0,-5.456 3.821863,-8.906666 9.986133,-8.906666 3.6992,0 6.5696,1.262933 8.34133,3.495466 l -4.30186,2.481067" />
|
||||
<path
|
||||
id="path3034"
|
||||
style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
|
||||
d="m 92.701867,38.997333 h 5.114666 v -20.9248 h -5.114666 z" />
|
||||
<path
|
||||
id="path3036"
|
||||
style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
|
||||
d="m 120.33067,33.438933 h 5.14453 v -1.245866 c 1.8208,1.9424 4.00747,2.9248 6.47253,2.9248 2.84054,0 4.992,-0.9824 6.1024,-2.653867 0.92587,-1.381333 0.98774,-3.0496 0.98774,-5.239467 v -9.152 h -5.15094 v 8.040534 c 0,3.336533 -0.67093,4.877866 -3.6,4.877866 -2.96106,0 -4.81173,-1.764266 -4.81173,-4.724266 v -8.194134 h -5.14453 v 15.3664" />
|
||||
<path
|
||||
id="path3038"
|
||||
style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
|
||||
d="m 155.60107,26.173867 c 0,-2.864 -1.9136,-4.741334 -4.8736,-4.741334 -2.96427,0 -4.87787,1.813334 -4.87787,4.709334 0,2.9376 1.88907,4.750933 4.87787,4.750933 2.96,0 4.8736,-1.8464 4.8736,-4.718933 z m 0,6.568533 c -1.30027,1.393067 -3.1808,2.157867 -5.79734,2.157867 -5.64266,0 -9.49546,-3.479467 -9.49546,-8.6944 0,-5.112534 3.82613,-8.688 9.40266,-8.688 2.5568,0 4.4352,0.645333 5.89014,2.096 v -1.541334 h 5.14666 v 22.2528 l -5.14666,-1.328 V 32.7424" />
|
||||
<path
|
||||
id="path3040"
|
||||
style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
|
||||
d="m 81.010133,30.8928 c 2.990934,0 4.871467,-1.813333 4.871467,-4.750933 0,-2.896 -1.9104,-4.709334 -4.871467,-4.709334 -2.958933,0 -4.869333,1.877334 -4.869333,4.741334 0,2.872533 1.9104,4.718933 4.869333,4.718933 z m -4.869333,8.104533 -5.1488,1.328 v -22.2528 h 5.1488 v 1.541334 c 1.448533,-1.450667 3.329067,-2.096 5.886933,-2.096 5.579734,0 9.4016,3.575466 9.4016,8.688 0,5.214933 -3.853866,8.6944 -9.493333,8.6944 -2.621867,0 -4.5024,-0.7648 -5.7952,-2.157867 v 6.254933" />
|
||||
<path
|
||||
id="path3042"
|
||||
style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
|
||||
d="m 183.2608,18.072533 v 15.3664 h 5.14667 v -0.9504 c 1.54026,1.857067 3.1712,2.7808 5.0272,2.7808 0.368,0 0.82986,-0.05973 1.44533,-0.1216 V 30.768 c -0.496,0.064 -1.04747,0.064 -1.6352,0.064 -2.992,0 -4.83733,-1.972267 -4.83733,-5.329067 v -7.4304 h -5.14667" />
|
||||
<path
|
||||
id="path3044"
|
||||
style="fill:#0d528a;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.77647352"
|
||||
d="m 201.55307,35.252267 h -0.39467 l 0.0139,1.409066 0.0203,0.466134 -0.1056,-0.384 -0.46826,-1.4912 h -0.36054 l -0.45866,1.4912 -0.1152,0.376533 0.0277,-0.458667 0.0139,-1.409066 h -0.38614 v 2.282666 h 0.54187 l 0.57067,-1.8016 0.5568,1.8016 h 0.544 z m -3.12747,0 h -0.39787 V 37.1968 h -0.7328 v 0.338133 h 1.85067 V 37.1968 h -0.72 v -1.944533" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
4
extern/carve/include/carve/win32.h
vendored
4
extern/carve/include/carve/win32.h
vendored
@@ -8,11 +8,9 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !defined(__MINGW32__)
|
||||
inline int strcasecmp(const char *a, const char *b) {
|
||||
return _stricmp(a,b);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void srandom(unsigned long input) {
|
||||
srand(input);
|
||||
@@ -34,7 +32,7 @@ typedef unsigned long uintptr_t;
|
||||
|
||||
# if _MSC_VER < 1600
|
||||
// stdint.h is not available before VS2010
|
||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
||||
#if defined(_WIN32)
|
||||
/* The __intXX are built-in types of the visual complier! So we don't
|
||||
need to include anything else here.
|
||||
This typedefs should be in sync with types from MEM_sys_types.h */
|
||||
|
15
extern/carve/patches/mingw.patch
vendored
15
extern/carve/patches/mingw.patch
vendored
@@ -1,15 +0,0 @@
|
||||
diff -r 525472fb477a include/carve/win32.h
|
||||
--- a/include/carve/win32.h Sun Jan 15 23:07:40 2012 -0500
|
||||
+++ b/include/carve/win32.h Wed Jan 18 00:40:10 2012 +0600
|
||||
@@ -8,9 +8,11 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
+#if !defined(__MINGW32__)
|
||||
inline int strcasecmp(const char *a, const char *b) {
|
||||
return _stricmp(a,b);
|
||||
}
|
||||
+#endif
|
||||
|
||||
inline void srandom(unsigned long input) {
|
||||
srand(input);
|
13
extern/carve/patches/mingw_w64.patch
vendored
13
extern/carve/patches/mingw_w64.patch
vendored
@@ -1,13 +0,0 @@
|
||||
Index: bundle.sh
|
||||
===================================================================
|
||||
--- bundle.sh (revision 45912)
|
||||
+++ bundle.sh (working copy)
|
||||
@@ -114,7 +114,7 @@
|
||||
if env['WITH_BF_BOOST']:
|
||||
if env['OURPLATFORM'] not in ('win32-vc', 'win64-vc'):
|
||||
# Boost is setting as preferred collections library in the Carve code when using MSVC compiler
|
||||
- if env['OURPLATFORM'] != 'win32-mingw':
|
||||
+ if env['OURPLATFORM'] not in ('win32-mingw', 'win64-mingw'):
|
||||
defs.append('HAVE_BOOST_UNORDERED_COLLECTIONS')
|
||||
|
||||
defs.append('CARVE_SYSTEM_BOOST')
|
1
extern/carve/patches/series
vendored
1
extern/carve/patches/series
vendored
@@ -1,7 +1,6 @@
|
||||
includes.patch
|
||||
win32.patch
|
||||
mesh_iterator.patch
|
||||
mingw.patch
|
||||
gcc46.patch
|
||||
clang_is_heap_fix.patch
|
||||
strict_flags.patch
|
||||
|
2
extern/carve/patches/win32.patch
vendored
2
extern/carve/patches/win32.patch
vendored
@@ -8,7 +8,7 @@ diff -r e82d852e4fb0 include/carve/win32.h
|
||||
-typedef char int8_t;
|
||||
-typedef short int16_t;
|
||||
-typedef long int32_t;
|
||||
+#if defined(_WIN32) && !defined(__MINGW32__)
|
||||
+#if defined(_WIN32)
|
||||
+/* The __intXX are built-in types of the visual complier! So we don't
|
||||
+ need to include anything else here.
|
||||
+ This typedefs should be in sync with types from MEM_sys_types.h */
|
||||
|
@@ -137,7 +137,7 @@ struct Knot {
|
||||
|
||||
/* Initially point to contiguous memory, however we may re-assign */
|
||||
double *tan[2];
|
||||
} Knot;
|
||||
};
|
||||
|
||||
|
||||
struct KnotRemoveState {
|
||||
@@ -1102,7 +1102,7 @@ int curve_fit_cubic_to_points_refit_db(
|
||||
uint **r_corner_index_array, uint *r_corner_index_len)
|
||||
{
|
||||
const uint knots_len = points_len;
|
||||
struct Knot *knots = malloc(sizeof(Knot) * knots_len);
|
||||
struct Knot *knots = malloc(sizeof(struct Knot) * knots_len);
|
||||
|
||||
#ifndef USE_CORNER_DETECT
|
||||
(void)r_corner_index_array;
|
||||
|
@@ -63,12 +63,7 @@
|
||||
#if defined(_MSC_VER)
|
||||
# define ATOMIC_INLINE static __forceinline
|
||||
#else
|
||||
# if (defined(__APPLE__) && defined(__ppc__))
|
||||
/* static inline __attribute__ here breaks osx ppc gcc42 build */
|
||||
# define ATOMIC_INLINE static __attribute__((always_inline))
|
||||
# else
|
||||
# define ATOMIC_INLINE static inline __attribute__((always_inline))
|
||||
# endif
|
||||
# define ATOMIC_INLINE static inline __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
#ifndef LIKELY
|
||||
|
@@ -19,7 +19,7 @@
|
||||
#
|
||||
# ***** END LGPL LICENSE BLOCK *****
|
||||
|
||||
remove_extra_strict_flags()
|
||||
remove_strict_flags()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
remove_cc_flag("-Wunused-macros")
|
||||
|
@@ -89,7 +89,7 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause(bool keep)
|
||||
}
|
||||
|
||||
AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, boost::shared_ptr<AUD_IReader> reader, boost::shared_ptr<AUD_PitchReader> pitch, boost::shared_ptr<AUD_ResampleReader> resampler, boost::shared_ptr<AUD_ChannelMapperReader> mapper, bool keep) :
|
||||
m_reader(reader), m_pitch(pitch), m_resampler(resampler), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_user_pan(0.0f), m_volume(1.0f), m_old_volume(1.0f), m_loopcount(0),
|
||||
m_reader(reader), m_pitch(pitch), m_resampler(resampler), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_user_pan(0.0f), m_volume(0.0f), m_old_volume(0.0f), m_loopcount(0),
|
||||
m_relative(true), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits<float>::max()),
|
||||
m_distance_reference(1.0f), m_attenuation(1.0f), m_cone_angle_outer(M_PI), m_cone_angle_inner(M_PI), m_cone_volume_outer(0),
|
||||
m_flags(AUD_RENDER_CONE), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING), m_device(device)
|
||||
|
@@ -239,14 +239,15 @@ def register_passes(engine, scene, srl):
|
||||
if crl.pass_debug_bvh_intersections: engine.register_pass(scene, srl, "Debug BVH Intersections", 1, "X", 'VALUE')
|
||||
if crl.pass_debug_ray_bounces: engine.register_pass(scene, srl, "Debug Ray Bounces", 1, "X", 'VALUE')
|
||||
|
||||
if crl.use_denoising and crl.denoising_store_passes:
|
||||
engine.register_pass(scene, srl, "Denoising Normal", 3, "XYZ", 'VECTOR');
|
||||
engine.register_pass(scene, srl, "Denoising Normal Variance", 3, "XYZ", 'VECTOR');
|
||||
engine.register_pass(scene, srl, "Denoising Albedo", 3, "RGB", 'COLOR');
|
||||
engine.register_pass(scene, srl, "Denoising Albedo Variance", 3, "RGB", 'COLOR');
|
||||
engine.register_pass(scene, srl, "Denoising Depth", 1, "Z", 'VALUE');
|
||||
engine.register_pass(scene, srl, "Denoising Depth Variance", 1, "Z", 'VALUE');
|
||||
engine.register_pass(scene, srl, "Denoising Shadow A", 3, "XYV", 'VECTOR');
|
||||
engine.register_pass(scene, srl, "Denoising Shadow B", 3, "XYV", 'VECTOR');
|
||||
engine.register_pass(scene, srl, "Denoising Image", 3, "RGB", 'COLOR');
|
||||
engine.register_pass(scene, srl, "Denoising Image Variance", 3, "RGB", 'COLOR');
|
||||
cscene = scene.cycles
|
||||
if crl.use_denoising and crl.denoising_store_passes and not cscene.use_progressive_refine:
|
||||
engine.register_pass(scene, srl, "Denoising Normal", 3, "XYZ", 'VECTOR')
|
||||
engine.register_pass(scene, srl, "Denoising Normal Variance", 3, "XYZ", 'VECTOR')
|
||||
engine.register_pass(scene, srl, "Denoising Albedo", 3, "RGB", 'COLOR')
|
||||
engine.register_pass(scene, srl, "Denoising Albedo Variance", 3, "RGB", 'COLOR')
|
||||
engine.register_pass(scene, srl, "Denoising Depth", 1, "Z", 'VALUE')
|
||||
engine.register_pass(scene, srl, "Denoising Depth Variance", 1, "Z", 'VALUE')
|
||||
engine.register_pass(scene, srl, "Denoising Shadow A", 3, "XYV", 'VECTOR')
|
||||
engine.register_pass(scene, srl, "Denoising Shadow B", 3, "XYV", 'VECTOR')
|
||||
engine.register_pass(scene, srl, "Denoising Image", 3, "RGB", 'COLOR')
|
||||
engine.register_pass(scene, srl, "Denoising Image Variance", 3, "RGB", 'COLOR')
|
||||
|
@@ -695,10 +695,17 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
||||
update=devices_update_callback
|
||||
)
|
||||
|
||||
cls.debug_opencl_kernel_single_program = BoolProperty(name="Single Program", default=True, update=devices_update_callback);
|
||||
cls.debug_opencl_kernel_single_program = BoolProperty(
|
||||
name="Single Program",
|
||||
default=True,
|
||||
update=devices_update_callback,
|
||||
)
|
||||
|
||||
cls.debug_use_opencl_debug = BoolProperty(name="Debug OpenCL", default=False)
|
||||
|
||||
cls.debug_opencl_mem_limit = IntProperty(name="Memory limit", default=0,
|
||||
description="Artificial limit on OpenCL memory usage in MB (0 to disable limit)")
|
||||
|
||||
@classmethod
|
||||
def unregister(cls):
|
||||
del bpy.types.Scene.cycles
|
||||
@@ -1166,6 +1173,12 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
|
||||
def unregister(cls):
|
||||
del bpy.types.Scene.cycles_curves
|
||||
|
||||
def update_render_passes(self, context):
|
||||
scene = context.scene
|
||||
rd = scene.render
|
||||
rl = rd.layers.active
|
||||
rl.update_render_passes()
|
||||
|
||||
class CyclesRenderLayerSettings(bpy.types.PropertyGroup):
|
||||
@classmethod
|
||||
def register(cls):
|
||||
@@ -1178,27 +1191,32 @@ class CyclesRenderLayerSettings(bpy.types.PropertyGroup):
|
||||
name="Debug BVH Traversed Nodes",
|
||||
description="Store Debug BVH Traversed Nodes pass",
|
||||
default=False,
|
||||
update=update_render_passes,
|
||||
)
|
||||
cls.pass_debug_bvh_traversed_instances = BoolProperty(
|
||||
name="Debug BVH Traversed Instances",
|
||||
description="Store Debug BVH Traversed Instances pass",
|
||||
default=False,
|
||||
update=update_render_passes,
|
||||
)
|
||||
cls.pass_debug_bvh_intersections = BoolProperty(
|
||||
name="Debug BVH Intersections",
|
||||
description="Store Debug BVH Intersections",
|
||||
default=False,
|
||||
update=update_render_passes,
|
||||
)
|
||||
cls.pass_debug_ray_bounces = BoolProperty(
|
||||
name="Debug Ray Bounces",
|
||||
description="Store Debug Ray Bounces pass",
|
||||
default=False,
|
||||
update=update_render_passes,
|
||||
)
|
||||
|
||||
cls.use_denoising = BoolProperty(
|
||||
name="Use Denoising",
|
||||
description="Denoise the rendered image",
|
||||
default=False,
|
||||
update=update_render_passes,
|
||||
)
|
||||
cls.denoising_diffuse_direct = BoolProperty(
|
||||
name="Diffuse Direct",
|
||||
@@ -1255,18 +1273,19 @@ class CyclesRenderLayerSettings(bpy.types.PropertyGroup):
|
||||
cls.denoising_radius = IntProperty(
|
||||
name="Denoising Radius",
|
||||
description="Size of the image area that's used to denoise a pixel (higher values are smoother, but might lose detail and are slower)",
|
||||
min=1, max=50,
|
||||
min=1, max=25,
|
||||
default=8,
|
||||
)
|
||||
cls.denoising_relative_pca = BoolProperty(
|
||||
name="Relative filter",
|
||||
description="When removing that don't carry information, use a relative threshold instead of an absolute one (can help to reduce artifacts, but might cause detail loss around edges)",
|
||||
description="When removing pixels that don't carry information, use a relative threshold instead of an absolute one (can help to reduce artifacts, but might cause detail loss around edges)",
|
||||
default=False,
|
||||
)
|
||||
cls.denoising_store_passes = BoolProperty(
|
||||
name="Store denoising passes",
|
||||
description="Store the denoising feature passes and the noisy image",
|
||||
default=False,
|
||||
update=update_render_passes,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
@@ -531,17 +531,17 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
|
||||
col.prop(rl, "use_pass_environment")
|
||||
|
||||
if context.scene.cycles.feature_set == 'EXPERIMENTAL':
|
||||
col.separator()
|
||||
sub = col.column()
|
||||
sub.active = crl.use_denoising
|
||||
sub.prop(crl, "denoising_store_passes", text="Denoising")
|
||||
col.separator()
|
||||
sub = col.column()
|
||||
sub.active = crl.use_denoising
|
||||
sub.prop(crl, "denoising_store_passes", text="Denoising")
|
||||
|
||||
if _cycles.with_cycles_debug:
|
||||
col = layout.column()
|
||||
col.prop(crl, "pass_debug_bvh_traversed_nodes")
|
||||
col.prop(crl, "pass_debug_bvh_traversed_instances")
|
||||
col.prop(crl, "pass_debug_bvh_intersections")
|
||||
col.prop(crl, "pass_debug_ray_bounces")
|
||||
col = layout.column()
|
||||
col.prop(crl, "pass_debug_bvh_traversed_nodes")
|
||||
col.prop(crl, "pass_debug_bvh_traversed_instances")
|
||||
col.prop(crl, "pass_debug_bvh_intersections")
|
||||
col.prop(crl, "pass_debug_ray_bounces")
|
||||
|
||||
|
||||
class CyclesRender_PT_views(CyclesButtonsPanel, Panel):
|
||||
@@ -596,16 +596,23 @@ class CyclesRender_PT_denoising(CyclesButtonsPanel, Panel):
|
||||
rd = context.scene.render
|
||||
rl = rd.layers.active
|
||||
crl = rl.cycles
|
||||
self.layout.prop(crl, "use_denoising", text="")
|
||||
cscene = context.scene.cycles
|
||||
layout = self.layout
|
||||
|
||||
layout.active = not cscene.use_progressive_refine
|
||||
layout.prop(crl, "use_denoising", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
scene = context.scene
|
||||
cscene = scene.cycles
|
||||
rd = scene.render
|
||||
rl = rd.layers.active
|
||||
crl = rl.cycles
|
||||
|
||||
layout.active = crl.use_denoising and not cscene.use_progressive_refine
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
@@ -1601,6 +1608,7 @@ class CyclesRender_PT_debug(CyclesButtonsPanel, Panel):
|
||||
col.prop(cscene, "debug_opencl_device_type", text="Device")
|
||||
col.prop(cscene, "debug_opencl_kernel_single_program", text="Single Program")
|
||||
col.prop(cscene, "debug_use_opencl_debug", text="Debug")
|
||||
col.prop(cscene, "debug_opencl_mem_limit")
|
||||
|
||||
|
||||
class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
|
||||
@@ -1703,7 +1711,7 @@ def draw_device(self, context):
|
||||
|
||||
layout.prop(cscene, "feature_set")
|
||||
|
||||
split = layout.split(percentage=1/3)
|
||||
split = layout.split(percentage=1 / 3)
|
||||
split.label("Device:")
|
||||
row = split.row()
|
||||
row.active = show_device_active(context)
|
||||
|
@@ -544,7 +544,11 @@ void BlenderSync::sync_camera_motion(BL::RenderSettings& b_render,
|
||||
|
||||
if(tfm != cam->matrix) {
|
||||
VLOG(1) << "Camera " << b_ob.name() << " motion detected.";
|
||||
if(motion_time == -1.0f) {
|
||||
if(motion_time == 0.0f) {
|
||||
/* When motion blur is not centered in frame, cam->matrix gets reset. */
|
||||
cam->matrix = tfm;
|
||||
}
|
||||
else if(motion_time == -1.0f) {
|
||||
cam->motion.pre = tfm;
|
||||
cam->use_motion = true;
|
||||
}
|
||||
@@ -573,7 +577,10 @@ void BlenderSync::sync_camera_motion(BL::RenderSettings& b_render,
|
||||
float fov = 2.0f * atanf((0.5f * sensor_size) / bcam.lens / aspectratio);
|
||||
if(fov != cam->fov) {
|
||||
VLOG(1) << "Camera " << b_ob.name() << " FOV change detected.";
|
||||
if(motion_time == -1.0f) {
|
||||
if(motion_time == 0.0f) {
|
||||
cam->fov = fov;
|
||||
}
|
||||
else if(motion_time == -1.0f) {
|
||||
cam->fov_pre = fov;
|
||||
cam->use_perspective_motion = true;
|
||||
}
|
||||
|
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include "render/mesh.h"
|
||||
#include "render/object.h"
|
||||
#include "render/scene.h"
|
||||
@@ -51,8 +50,7 @@ enum {
|
||||
* Two triangles has vertex indices in the original Blender-side face.
|
||||
* If face is already a quad tri_b will not be initialized.
|
||||
*/
|
||||
inline void face_split_tri_indices(const int num_verts,
|
||||
const int face_flag,
|
||||
inline void face_split_tri_indices(const int face_flag,
|
||||
int tri_a[3],
|
||||
int tri_b[3])
|
||||
{
|
||||
@@ -60,21 +58,19 @@ inline void face_split_tri_indices(const int num_verts,
|
||||
tri_a[0] = 0;
|
||||
tri_a[1] = 1;
|
||||
tri_a[2] = 3;
|
||||
if(num_verts == 4) {
|
||||
tri_b[0] = 2;
|
||||
tri_b[1] = 3;
|
||||
tri_b[2] = 1;
|
||||
}
|
||||
|
||||
tri_b[0] = 2;
|
||||
tri_b[1] = 3;
|
||||
tri_b[2] = 1;
|
||||
}
|
||||
else /*if(face_flag & FACE_FLAG_DIVIDE_13)*/ {
|
||||
tri_a[0] = 0;
|
||||
tri_a[1] = 1;
|
||||
tri_a[2] = 2;
|
||||
if(num_verts == 4) {
|
||||
tri_b[0] = 0;
|
||||
tri_b[1] = 2;
|
||||
tri_b[2] = 3;
|
||||
}
|
||||
|
||||
tri_b[0] = 0;
|
||||
tri_b[1] = 2;
|
||||
tri_b[2] = 3;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,7 +247,7 @@ static void mikk_compute_tangents(BL::Mesh& b_mesh,
|
||||
|
||||
for(int i = 0; i < nverts.size(); i++) {
|
||||
int tri_a[3], tri_b[3];
|
||||
face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);
|
||||
face_split_tri_indices(face_flags[i], tri_a, tri_b);
|
||||
|
||||
tangent[0] = float4_to_float3(userdata.tangent[i*4 + tri_a[0]]);
|
||||
tangent[1] = float4_to_float3(userdata.tangent[i*4 + tri_a[1]]);
|
||||
@@ -293,7 +289,7 @@ static void create_mesh_volume_attribute(BL::Object& b_ob,
|
||||
|
||||
if(!b_domain)
|
||||
return;
|
||||
|
||||
|
||||
Attribute *attr = mesh->attributes.add(std);
|
||||
VoxelAttribute *volume_data = attr->data_voxel();
|
||||
bool is_float, is_linear;
|
||||
@@ -377,7 +373,7 @@ static void attr_create_vertex_color(Scene *scene,
|
||||
|
||||
for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
|
||||
int tri_a[3], tri_b[3];
|
||||
face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);
|
||||
face_split_tri_indices(face_flags[i], tri_a, tri_b);
|
||||
|
||||
uchar4 colors[4];
|
||||
colors[0] = color_float_to_byte(color_srgb_to_scene_linear_v3(get_float3(c->color1())));
|
||||
@@ -470,7 +466,7 @@ static void attr_create_uv_map(Scene *scene,
|
||||
|
||||
for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
|
||||
int tri_a[3], tri_b[3];
|
||||
face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);
|
||||
face_split_tri_indices(face_flags[i], tri_a, tri_b);
|
||||
|
||||
float3 uvs[4];
|
||||
uvs[0] = get_float3(t->uv1());
|
||||
@@ -982,7 +978,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
|
||||
else
|
||||
used_shaders.push_back(scene->default_surface);
|
||||
}
|
||||
|
||||
|
||||
/* test if we need to sync */
|
||||
int requested_geometry_flags = Mesh::GEOMETRY_NONE;
|
||||
if(render_layer.use_surfaces) {
|
||||
@@ -1017,12 +1013,12 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
|
||||
/* ensure we only sync instanced meshes once */
|
||||
if(mesh_synced.find(mesh) != mesh_synced.end())
|
||||
return mesh;
|
||||
|
||||
|
||||
mesh_synced.insert(mesh);
|
||||
|
||||
/* create derived mesh */
|
||||
array<int> oldtriangle = mesh->triangles;
|
||||
|
||||
|
||||
/* compares curve_keys rather than strands in order to handle quick hair
|
||||
* adjustments in dynamic BVH - other methods could probably do this better*/
|
||||
array<float3> oldcurve_keys = mesh->curve_keys;
|
||||
@@ -1111,7 +1107,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
|
||||
if(memcmp(&oldcurve_radius[0], &mesh->curve_radius[0], sizeof(float)*oldcurve_radius.size()) != 0)
|
||||
rebuild = true;
|
||||
}
|
||||
|
||||
|
||||
mesh->tag_update(scene, rebuild);
|
||||
|
||||
return mesh;
|
||||
@@ -1140,7 +1136,7 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
|
||||
if(scene->need_motion() == Scene::MOTION_BLUR) {
|
||||
if(!mesh->use_motion_blur)
|
||||
return;
|
||||
|
||||
|
||||
/* see if this mesh needs motion data at this time */
|
||||
vector<float> object_times = object->motion_times();
|
||||
bool found = false;
|
||||
@@ -1172,7 +1168,7 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
|
||||
|
||||
if(!numverts && !numkeys)
|
||||
return;
|
||||
|
||||
|
||||
/* skip objects without deforming modifiers. this is not totally reliable,
|
||||
* would need a more extensive check to see which objects are animated */
|
||||
BL::Mesh b_mesh(PointerRNA_NULL);
|
||||
|
@@ -106,6 +106,7 @@ bool debug_flags_sync_from_scene(BL::Scene b_scene)
|
||||
}
|
||||
/* Synchronize other OpenCL flags. */
|
||||
flags.opencl.debug = get_boolean(cscene, "debug_use_opencl_debug");
|
||||
flags.opencl.mem_limit = ((size_t)get_int(cscene, "debug_opencl_mem_limit"))*1024*1024;
|
||||
flags.opencl.single_program = get_boolean(cscene, "debug_opencl_kernel_single_program");
|
||||
return flags.opencl.device_type != opencl_device_type ||
|
||||
flags.opencl.kernel_type != opencl_kernel_type;
|
||||
|
@@ -129,9 +129,9 @@ void BlenderSession::create_session()
|
||||
scene = new Scene(scene_params, session_params.device);
|
||||
|
||||
/* setup callbacks for builtin image support */
|
||||
scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3, _4, _5, _6, _7);
|
||||
scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3, _4);
|
||||
scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2, _3, _4);
|
||||
scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3, _4, _5, _6, _7, _8);
|
||||
scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3, _4, _5);
|
||||
scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2, _3, _4, _5);
|
||||
|
||||
/* create session */
|
||||
session = new Session(session_params);
|
||||
@@ -399,20 +399,14 @@ void BlenderSession::render()
|
||||
BL::RenderLayer b_rlay = *b_single_rlay;
|
||||
|
||||
/* add passes */
|
||||
array<Pass> passes;
|
||||
if(session_params.device.advanced_shading) {
|
||||
passes = sync->sync_render_passes(b_rlay, *b_layer_iter);
|
||||
}
|
||||
else {
|
||||
Pass::add(PASS_COMBINED, passes);
|
||||
}
|
||||
|
||||
array<Pass> passes = sync->sync_render_passes(b_rlay, *b_layer_iter, session_params);
|
||||
buffer_params.passes = passes;
|
||||
|
||||
PointerRNA crl = RNA_pointer_get(&b_layer_iter->ptr, "cycles");
|
||||
buffer_params.denoising_data_pass = get_boolean(crl, "use_denoising");
|
||||
session->tile_manager.schedule_denoising = get_boolean(crl, "use_denoising");
|
||||
session->params.use_denoising = get_boolean(crl, "use_denoising");
|
||||
bool use_denoising = !session_params.progressive_refine && get_boolean(crl, "use_denoising");
|
||||
buffer_params.denoising_data_pass = use_denoising;
|
||||
session->tile_manager.schedule_denoising = use_denoising;
|
||||
session->params.use_denoising = use_denoising;
|
||||
scene->film->denoising_data_pass = buffer_params.denoising_data_pass;
|
||||
scene->film->denoising_flags = 0;
|
||||
if(!get_boolean(crl, "denoising_diffuse_direct")) scene->film->denoising_flags |= DENOISING_CLEAN_DIFFUSE_DIR;
|
||||
@@ -564,8 +558,6 @@ void BlenderSession::bake(BL::Object& b_object,
|
||||
float result[])
|
||||
{
|
||||
ShaderEvalType shader_type = get_shader_type(pass_type);
|
||||
size_t object_index = OBJECT_NONE;
|
||||
int tri_offset = 0;
|
||||
|
||||
/* Set baking flag in advance, so kernel loading can check if we need
|
||||
* any baking capabilities.
|
||||
@@ -575,9 +567,6 @@ void BlenderSession::bake(BL::Object& b_object,
|
||||
/* ensure kernels are loaded before we do any scene updates */
|
||||
session->load_kernels();
|
||||
|
||||
if(session->progress.get_cancel())
|
||||
return;
|
||||
|
||||
if(shader_type == SHADER_EVAL_UV) {
|
||||
/* force UV to be available */
|
||||
Pass::add(PASS_UV, scene->film->passes);
|
||||
@@ -595,50 +584,61 @@ void BlenderSession::bake(BL::Object& b_object,
|
||||
scene->film->tag_update(scene);
|
||||
scene->integrator->tag_update(scene);
|
||||
|
||||
/* update scene */
|
||||
BL::Object b_camera_override(b_engine.camera_override());
|
||||
sync->sync_camera(b_render, b_camera_override, width, height, "");
|
||||
sync->sync_data(b_render,
|
||||
b_v3d,
|
||||
b_camera_override,
|
||||
width, height,
|
||||
&python_thread_state,
|
||||
b_rlay_name.c_str());
|
||||
|
||||
/* get buffer parameters */
|
||||
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
|
||||
BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
|
||||
|
||||
scene->bake_manager->set_shader_limit((size_t)b_engine.tile_x(), (size_t)b_engine.tile_y());
|
||||
|
||||
/* set number of samples */
|
||||
session->tile_manager.set_samples(session_params.samples);
|
||||
session->reset(buffer_params, session_params.samples);
|
||||
session->update_scene();
|
||||
|
||||
/* find object index. todo: is arbitrary - copied from mesh_displace.cpp */
|
||||
for(size_t i = 0; i < scene->objects.size(); i++) {
|
||||
if(strcmp(scene->objects[i]->name.c_str(), b_object.name().c_str()) == 0) {
|
||||
object_index = i;
|
||||
tri_offset = scene->objects[i]->mesh->tri_offset;
|
||||
break;
|
||||
}
|
||||
if(!session->progress.get_cancel()) {
|
||||
/* update scene */
|
||||
BL::Object b_camera_override(b_engine.camera_override());
|
||||
sync->sync_camera(b_render, b_camera_override, width, height, "");
|
||||
sync->sync_data(b_render,
|
||||
b_v3d,
|
||||
b_camera_override,
|
||||
width, height,
|
||||
&python_thread_state,
|
||||
b_rlay_name.c_str());
|
||||
}
|
||||
|
||||
int object = object_index;
|
||||
BakeData *bake_data = NULL;
|
||||
|
||||
BakeData *bake_data = scene->bake_manager->init(object, tri_offset, num_pixels);
|
||||
if(!session->progress.get_cancel()) {
|
||||
/* get buffer parameters */
|
||||
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
|
||||
BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
|
||||
|
||||
populate_bake_data(bake_data, object_id, pixel_array, num_pixels);
|
||||
scene->bake_manager->set_shader_limit((size_t)b_engine.tile_x(), (size_t)b_engine.tile_y());
|
||||
|
||||
/* set number of samples */
|
||||
session->tile_manager.set_samples(session_params.samples);
|
||||
session->reset(buffer_params, session_params.samples);
|
||||
session->update_scene();
|
||||
/* set number of samples */
|
||||
session->tile_manager.set_samples(session_params.samples);
|
||||
session->reset(buffer_params, session_params.samples);
|
||||
session->update_scene();
|
||||
|
||||
session->progress.set_update_callback(function_bind(&BlenderSession::update_bake_progress, this));
|
||||
/* find object index. todo: is arbitrary - copied from mesh_displace.cpp */
|
||||
size_t object_index = OBJECT_NONE;
|
||||
int tri_offset = 0;
|
||||
|
||||
scene->bake_manager->bake(scene->device, &scene->dscene, scene, session->progress, shader_type, bake_pass_filter, bake_data, result);
|
||||
for(size_t i = 0; i < scene->objects.size(); i++) {
|
||||
if(strcmp(scene->objects[i]->name.c_str(), b_object.name().c_str()) == 0) {
|
||||
object_index = i;
|
||||
tri_offset = scene->objects[i]->mesh->tri_offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int object = object_index;
|
||||
|
||||
bake_data = scene->bake_manager->init(object, tri_offset, num_pixels);
|
||||
populate_bake_data(bake_data, object_id, pixel_array, num_pixels);
|
||||
|
||||
/* set number of samples */
|
||||
session->tile_manager.set_samples(session_params.samples);
|
||||
session->reset(buffer_params, session_params.samples);
|
||||
session->update_scene();
|
||||
|
||||
session->progress.set_update_callback(function_bind(&BlenderSession::update_bake_progress, this));
|
||||
}
|
||||
|
||||
/* Perform bake. Check cancel to avoid crash with incomplete scene data. */
|
||||
if(!session->progress.get_cancel()) {
|
||||
scene->bake_manager->bake(scene->device, &scene->dscene, scene, session->progress, shader_type, bake_pass_filter, bake_data, result);
|
||||
}
|
||||
|
||||
/* free all memory used (host and device), so we wouldn't leave render
|
||||
* engine with extra memory allocated
|
||||
@@ -1013,7 +1013,8 @@ void BlenderSession::builtin_image_info(const string &builtin_name,
|
||||
int &width,
|
||||
int &height,
|
||||
int &depth,
|
||||
int &channels)
|
||||
int &channels,
|
||||
bool& free_cache)
|
||||
{
|
||||
/* empty image */
|
||||
is_float = false;
|
||||
@@ -1021,6 +1022,7 @@ void BlenderSession::builtin_image_info(const string &builtin_name,
|
||||
height = 1;
|
||||
depth = 0;
|
||||
channels = 0;
|
||||
free_cache = false;
|
||||
|
||||
if(!builtin_data)
|
||||
return;
|
||||
@@ -1034,6 +1036,7 @@ void BlenderSession::builtin_image_info(const string &builtin_name,
|
||||
/* image data */
|
||||
BL::Image b_image(b_id);
|
||||
|
||||
free_cache = !b_image.has_data();
|
||||
is_float = b_image.is_float();
|
||||
width = b_image.size()[0];
|
||||
height = b_image.size()[1];
|
||||
@@ -1094,7 +1097,8 @@ void BlenderSession::builtin_image_info(const string &builtin_name,
|
||||
bool BlenderSession::builtin_image_pixels(const string &builtin_name,
|
||||
void *builtin_data,
|
||||
unsigned char *pixels,
|
||||
const size_t pixels_size)
|
||||
const size_t pixels_size,
|
||||
const bool free_cache)
|
||||
{
|
||||
if(!builtin_data) {
|
||||
return false;
|
||||
@@ -1115,7 +1119,6 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name,
|
||||
|
||||
if(image_pixels && num_pixels * channels == pixels_size) {
|
||||
memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char));
|
||||
MEM_freeN(image_pixels);
|
||||
}
|
||||
else {
|
||||
if(channels == 1) {
|
||||
@@ -1134,6 +1137,16 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(image_pixels) {
|
||||
MEM_freeN(image_pixels);
|
||||
}
|
||||
|
||||
/* Free image buffers to save memory during render. */
|
||||
if(free_cache) {
|
||||
b_image.buffers_free();
|
||||
}
|
||||
|
||||
/* Premultiply, byte images are always straight for Blender. */
|
||||
unsigned char *cp = pixels;
|
||||
for(size_t i = 0; i < num_pixels; i++, cp += channels) {
|
||||
@@ -1147,7 +1160,8 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name,
|
||||
bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
|
||||
void *builtin_data,
|
||||
float *pixels,
|
||||
const size_t pixels_size)
|
||||
const size_t pixels_size,
|
||||
const bool free_cache)
|
||||
{
|
||||
if(!builtin_data) {
|
||||
return false;
|
||||
@@ -1172,7 +1186,6 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
|
||||
|
||||
if(image_pixels && num_pixels * channels == pixels_size) {
|
||||
memcpy(pixels, image_pixels, pixels_size * sizeof(float));
|
||||
MEM_freeN(image_pixels);
|
||||
}
|
||||
else {
|
||||
if(channels == 1) {
|
||||
@@ -1192,6 +1205,15 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
|
||||
}
|
||||
}
|
||||
|
||||
if(image_pixels) {
|
||||
MEM_freeN(image_pixels);
|
||||
}
|
||||
|
||||
/* Free image buffers to save memory during render. */
|
||||
if(free_cache) {
|
||||
b_image.buffers_free();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if(b_id.is_a(&RNA_Object)) {
|
||||
|
@@ -156,15 +156,18 @@ protected:
|
||||
int &width,
|
||||
int &height,
|
||||
int &depth,
|
||||
int &channels);
|
||||
int &channels,
|
||||
bool &free_cache);
|
||||
bool builtin_image_pixels(const string &builtin_name,
|
||||
void *builtin_data,
|
||||
unsigned char *pixels,
|
||||
const size_t pixels_size);
|
||||
const size_t pixels_size,
|
||||
const bool free_cache);
|
||||
bool builtin_image_float_pixels(const string &builtin_name,
|
||||
void *builtin_data,
|
||||
float *pixels,
|
||||
const size_t pixels_size);
|
||||
const size_t pixels_size,
|
||||
const bool free_cache);
|
||||
|
||||
/* Update tile manager to reflect resumable render settings. */
|
||||
void update_resumable_tile_manager(int num_samples);
|
||||
|
@@ -329,6 +329,9 @@ void BlenderSync::sync_integrator()
|
||||
integrator->ao_bounces = get_int(cscene, "ao_bounces_render");
|
||||
}
|
||||
}
|
||||
else {
|
||||
integrator->ao_bounces = 0;
|
||||
}
|
||||
|
||||
if(integrator->modified(previntegrator))
|
||||
integrator->tag_update(scene);
|
||||
@@ -550,11 +553,16 @@ int BlenderSync::get_denoising_pass(BL::RenderPass& b_pass)
|
||||
}
|
||||
|
||||
array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
|
||||
BL::SceneRenderLayer& b_srlay)
|
||||
BL::SceneRenderLayer& b_srlay,
|
||||
const SessionParams &session_params)
|
||||
{
|
||||
array<Pass> passes;
|
||||
Pass::add(PASS_COMBINED, passes);
|
||||
|
||||
if(!session_params.device.advanced_shading) {
|
||||
return passes;
|
||||
}
|
||||
|
||||
/* loop over passes */
|
||||
BL::RenderLayer::passes_iterator b_pass_iter;
|
||||
|
||||
@@ -569,7 +577,9 @@ array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
|
||||
}
|
||||
|
||||
PointerRNA crp = RNA_pointer_get(&b_srlay.ptr, "cycles");
|
||||
if(get_boolean(crp, "denoising_store_passes")) {
|
||||
if(get_boolean(crp, "denoising_store_passes") &&
|
||||
get_boolean(crp, "use_denoising") &&
|
||||
!session_params.progressive_refine) {
|
||||
b_engine.add_pass("Denoising Normal", 3, "XYZ", b_srlay.name().c_str());
|
||||
b_engine.add_pass("Denoising Normal Variance", 3, "XYZ", b_srlay.name().c_str());
|
||||
b_engine.add_pass("Denoising Albedo", 3, "RGB", b_srlay.name().c_str());
|
||||
@@ -598,8 +608,6 @@ array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
|
||||
b_engine.add_pass("Debug Ray Bounces", 1, "X", b_srlay.name().c_str());
|
||||
Pass::add(PASS_RAY_BOUNCES, passes);
|
||||
}
|
||||
#else
|
||||
(void) b_srlay; /* Ignored. */
|
||||
#endif
|
||||
|
||||
return passes;
|
||||
|
@@ -68,7 +68,8 @@ public:
|
||||
const char *layer = 0);
|
||||
void sync_render_layers(BL::SpaceView3D& b_v3d, const char *layer);
|
||||
array<Pass> sync_render_passes(BL::RenderLayer& b_rlay,
|
||||
BL::SceneRenderLayer& b_srlay);
|
||||
BL::SceneRenderLayer& b_srlay,
|
||||
const SessionParams &session_params);
|
||||
void sync_integrator();
|
||||
void sync_camera(BL::RenderSettings& b_render,
|
||||
BL::Object& b_override,
|
||||
|
@@ -51,8 +51,8 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
|
||||
bool calc_undeformed,
|
||||
Mesh::SubdivisionType subdivision_type)
|
||||
{
|
||||
bool subsurf_mod_show_render;
|
||||
bool subsurf_mod_show_viewport;
|
||||
bool subsurf_mod_show_render = false;
|
||||
bool subsurf_mod_show_viewport = false;
|
||||
|
||||
if(subdivision_type != Mesh::SUBDIVISION_NONE) {
|
||||
BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
|
||||
@@ -299,7 +299,7 @@ static inline uint get_layer(const BL::Array<int, 20>& array)
|
||||
for(uint i = 0; i < 20; i++)
|
||||
if(array[i])
|
||||
layer |= (1 << i);
|
||||
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
@@ -434,7 +434,7 @@ static inline string get_string(PointerRNA& ptr, const char *name)
|
||||
string str(cstr);
|
||||
if(cstr != cstrbuf)
|
||||
MEM_freeN(cstr);
|
||||
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -451,7 +451,7 @@ static inline string blender_absolute_path(BL::BlendData& b_data,
|
||||
{
|
||||
if(path.size() >= 2 && path[0] == '/' && path[1] == '/') {
|
||||
string dirname;
|
||||
|
||||
|
||||
if(b_id.library()) {
|
||||
BL::ID b_library_id(b_id.library());
|
||||
dirname = blender_absolute_path(b_data,
|
||||
@@ -544,7 +544,7 @@ static inline BL::SmokeDomainSettings object_smoke_domain_find(BL::Object& b_ob)
|
||||
return b_smd.domain_settings();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return BL::SmokeDomainSettings(PointerRNA_NULL);
|
||||
}
|
||||
|
||||
@@ -816,4 +816,3 @@ protected:
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BLENDER_UTIL_H__ */
|
||||
|
||||
|
@@ -242,21 +242,23 @@ void BVH4::pack_unaligned_node(int idx,
|
||||
* so kernel might safely assume there are always 4 child nodes.
|
||||
*/
|
||||
|
||||
data[1][i] = 1.0f;
|
||||
const float inf = FLT_MAX / 1000.0f;
|
||||
|
||||
data[1][i] = inf;
|
||||
data[2][i] = 0.0f;
|
||||
data[3][i] = 0.0f;
|
||||
|
||||
data[4][i] = 0.0f;
|
||||
data[5][i] = 0.0f;
|
||||
data[5][i] = inf;
|
||||
data[6][i] = 0.0f;
|
||||
|
||||
data[7][i] = 0.0f;
|
||||
data[8][i] = 0.0f;
|
||||
data[9][i] = 0.0f;
|
||||
data[9][i] = inf;
|
||||
|
||||
data[10][i] = -FLT_MAX;
|
||||
data[11][i] = -FLT_MAX;
|
||||
data[12][i] = -FLT_MAX;
|
||||
data[10][i] = -inf;
|
||||
data[11][i] = -inf;
|
||||
data[12][i] = -inf;
|
||||
|
||||
data[13][i] = __int_as_float(0);
|
||||
}
|
||||
|
@@ -1040,7 +1040,6 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
|
||||
*/
|
||||
start_index = spatial_free_index;
|
||||
spatial_free_index += range.size();
|
||||
|
||||
/* Extend an array when needed. */
|
||||
const size_t range_end = start_index + range.size();
|
||||
if(prim_type.size() < range_end) {
|
||||
@@ -1066,8 +1065,6 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
|
||||
prim_time.resize(range_end);
|
||||
}
|
||||
}
|
||||
spatial_spin_lock.unlock();
|
||||
|
||||
/* Perform actual data copy. */
|
||||
if(new_leaf_data_size > 0) {
|
||||
memcpy(&prim_type[start_index], &local_prim_type[0], new_leaf_data_size);
|
||||
@@ -1077,6 +1074,7 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
|
||||
memcpy(&prim_time[start_index], &local_prim_time[0], sizeof(float2)*num_new_leaf_data);
|
||||
}
|
||||
}
|
||||
spatial_spin_lock.unlock();
|
||||
}
|
||||
else {
|
||||
/* For the regular BVH builder we simply copy new data starting at the
|
||||
|
@@ -68,6 +68,8 @@ std::ostream& operator <<(std::ostream &os,
|
||||
<< string_from_bool(requested_features.use_transparent) << std::endl;
|
||||
os << "Use Principled BSDF: "
|
||||
<< string_from_bool(requested_features.use_principled) << std::endl;
|
||||
os << "Use Denoising: "
|
||||
<< string_from_bool(requested_features.use_denoising) << std::endl;
|
||||
return os;
|
||||
}
|
||||
|
||||
|
@@ -127,6 +127,9 @@ public:
|
||||
/* Per-uber shader usage flags. */
|
||||
bool use_principled;
|
||||
|
||||
/* Denoising features. */
|
||||
bool use_denoising;
|
||||
|
||||
DeviceRequestedFeatures()
|
||||
{
|
||||
/* TODO(sergey): Find more meaningful defaults. */
|
||||
@@ -145,6 +148,7 @@ public:
|
||||
use_transparent = false;
|
||||
use_shadow_tricks = false;
|
||||
use_principled = false;
|
||||
use_denoising = false;
|
||||
}
|
||||
|
||||
bool modified(const DeviceRequestedFeatures& requested_features)
|
||||
@@ -163,7 +167,8 @@ public:
|
||||
use_patch_evaluation == requested_features.use_patch_evaluation &&
|
||||
use_transparent == requested_features.use_transparent &&
|
||||
use_shadow_tricks == requested_features.use_shadow_tricks &&
|
||||
use_principled == requested_features.use_principled);
|
||||
use_principled == requested_features.use_principled &&
|
||||
use_denoising == requested_features.use_denoising);
|
||||
}
|
||||
|
||||
/* Convert the requested features structure to a build options,
|
||||
@@ -213,6 +218,9 @@ public:
|
||||
if(!use_principled) {
|
||||
build_options += " -D__NO_PRINCIPLED__";
|
||||
}
|
||||
if(!use_denoising) {
|
||||
build_options += " -D__NO_DENOISING__";
|
||||
}
|
||||
return build_options;
|
||||
}
|
||||
};
|
||||
|
@@ -119,7 +119,7 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
if(strstr(architecture_name, logged_architecture) != 0) {
|
||||
if(strcmp(architecture_name, logged_architecture) != 0) {
|
||||
VLOG(1) << "Will be using " << architecture_name << " kernels.";
|
||||
logged_architecture = architecture_name;
|
||||
}
|
||||
@@ -149,7 +149,8 @@ public:
|
||||
device_memory& use_queues_flag,
|
||||
device_memory& work_pool_wgs);
|
||||
|
||||
virtual SplitKernelFunction* get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&);
|
||||
virtual SplitKernelFunction* get_split_kernel_function(const string& kernel_name,
|
||||
const DeviceRequestedFeatures&);
|
||||
virtual int2 split_kernel_local_size();
|
||||
virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task);
|
||||
virtual uint64_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads);
|
||||
@@ -176,6 +177,7 @@ public:
|
||||
|
||||
KernelFunctions<void(*)(int, TilesInfo*, int, int, float*, float*, float*, float*, float*, int*, int, int, bool)> filter_divide_shadow_kernel;
|
||||
KernelFunctions<void(*)(int, TilesInfo*, int, int, int, int, float*, float*, int*, int, int, bool)> filter_get_feature_kernel;
|
||||
KernelFunctions<void(*)(int, int, float*, float*, float*, float*, int*, int)> filter_detect_outliers_kernel;
|
||||
KernelFunctions<void(*)(int, int, float*, float*, float*, float*, int*, int)> filter_combine_halves_kernel;
|
||||
|
||||
KernelFunctions<void(*)(int, int, float*, float*, float*, int*, int, int, float, float)> filter_nlm_calc_difference_kernel;
|
||||
@@ -184,9 +186,9 @@ public:
|
||||
KernelFunctions<void(*)(int, int, float*, float*, float*, float*, int*, int, int)> filter_nlm_update_output_kernel;
|
||||
KernelFunctions<void(*)(float*, float*, int*, int)> filter_nlm_normalize_kernel;
|
||||
|
||||
KernelFunctions<void(*)(float*, int, int, int, float*, int*, int*, int, int, float)> filter_construct_transform_kernel;
|
||||
KernelFunctions<void(*)(int, int, float*, float*, float*, float*, float*, int*, float*, float3*, int*, int*, int, int, int, int)> filter_nlm_construct_gramian_kernel;
|
||||
KernelFunctions<void(*)(int, int, int, int, int, float*, int*, float*, float3*, int*, int)> filter_finalize_kernel;
|
||||
KernelFunctions<void(*)(float*, int, int, int, float*, int*, int*, int, int, float)> filter_construct_transform_kernel;
|
||||
KernelFunctions<void(*)(int, int, float*, float*, float*, int*, float*, float3*, int*, int*, int, int, int, int)> filter_nlm_construct_gramian_kernel;
|
||||
KernelFunctions<void(*)(int, int, int, int, int, float*, int*, float*, float3*, int*, int)> filter_finalize_kernel;
|
||||
|
||||
KernelFunctions<void(*)(KernelGlobals *, ccl_constant KernelData*, ccl_global void*, int, ccl_global char*,
|
||||
ccl_global uint*, int, int, int, int, int, int, int, int, ccl_global int*, int,
|
||||
@@ -210,6 +212,7 @@ public:
|
||||
REGISTER_KERNEL(shader),
|
||||
REGISTER_KERNEL(filter_divide_shadow),
|
||||
REGISTER_KERNEL(filter_get_feature),
|
||||
REGISTER_KERNEL(filter_detect_outliers),
|
||||
REGISTER_KERNEL(filter_combine_halves),
|
||||
REGISTER_KERNEL(filter_nlm_calc_difference),
|
||||
REGISTER_KERNEL(filter_nlm_blur),
|
||||
@@ -246,6 +249,7 @@ public:
|
||||
REGISTER_SPLIT_KERNEL(direct_lighting);
|
||||
REGISTER_SPLIT_KERNEL(shadow_blocked_ao);
|
||||
REGISTER_SPLIT_KERNEL(shadow_blocked_dl);
|
||||
REGISTER_SPLIT_KERNEL(enqueue_inactive);
|
||||
REGISTER_SPLIT_KERNEL(next_iteration_setup);
|
||||
REGISTER_SPLIT_KERNEL(indirect_subsurface);
|
||||
REGISTER_SPLIT_KERNEL(buffer_update);
|
||||
@@ -463,8 +467,6 @@ public:
|
||||
|
||||
bool denoising_reconstruct(device_ptr color_ptr,
|
||||
device_ptr color_variance_ptr,
|
||||
device_ptr guide_ptr,
|
||||
device_ptr guide_variance_ptr,
|
||||
device_ptr output_ptr,
|
||||
DenoisingTask *task)
|
||||
{
|
||||
@@ -483,8 +485,8 @@ public:
|
||||
task->reconstruction_state.source_w - max(0, dx),
|
||||
task->reconstruction_state.source_h - max(0, dy)};
|
||||
filter_nlm_calc_difference_kernel()(dx, dy,
|
||||
(float*) guide_ptr,
|
||||
(float*) guide_variance_ptr,
|
||||
(float*) color_ptr,
|
||||
(float*) color_variance_ptr,
|
||||
difference,
|
||||
local_rect,
|
||||
task->buffer.w,
|
||||
@@ -497,8 +499,6 @@ public:
|
||||
filter_nlm_construct_gramian_kernel()(dx, dy,
|
||||
blurDifference,
|
||||
(float*) task->buffer.mem.device_pointer,
|
||||
(float*) color_ptr,
|
||||
(float*) color_variance_ptr,
|
||||
(float*) task->storage.transform.device_pointer,
|
||||
(int*) task->storage.rank.device_pointer,
|
||||
(float*) task->storage.XtWX.device_pointer,
|
||||
@@ -530,9 +530,8 @@ public:
|
||||
|
||||
bool denoising_combine_halves(device_ptr a_ptr, device_ptr b_ptr,
|
||||
device_ptr mean_ptr, device_ptr variance_ptr,
|
||||
int r, int4 rect, DenoisingTask *task)
|
||||
int r, int4 rect, DenoisingTask * /*task*/)
|
||||
{
|
||||
(void) task;
|
||||
for(int y = rect.y; y < rect.w; y++) {
|
||||
for(int x = rect.x; x < rect.z; x++) {
|
||||
filter_combine_halves_kernel()(x, y,
|
||||
@@ -594,6 +593,26 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool denoising_detect_outliers(device_ptr image_ptr,
|
||||
device_ptr variance_ptr,
|
||||
device_ptr depth_ptr,
|
||||
device_ptr output_ptr,
|
||||
DenoisingTask *task)
|
||||
{
|
||||
for(int y = task->rect.y; y < task->rect.w; y++) {
|
||||
for(int x = task->rect.x; x < task->rect.z; x++) {
|
||||
filter_detect_outliers_kernel()(x, y,
|
||||
(float*) image_ptr,
|
||||
(float*) variance_ptr,
|
||||
(float*) depth_ptr,
|
||||
(float*) output_ptr,
|
||||
&task->rect.x,
|
||||
task->buffer.pass_stride);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void path_trace(DeviceTask &task, RenderTile &tile, KernelGlobals *kg)
|
||||
{
|
||||
float *render_buffer = (float*)tile.buffer;
|
||||
@@ -627,11 +646,12 @@ public:
|
||||
DenoisingTask denoising(this);
|
||||
|
||||
denoising.functions.construct_transform = function_bind(&CPUDevice::denoising_construct_transform, this, &denoising);
|
||||
denoising.functions.reconstruct = function_bind(&CPUDevice::denoising_reconstruct, this, _1, _2, _3, _4, _5, &denoising);
|
||||
denoising.functions.reconstruct = function_bind(&CPUDevice::denoising_reconstruct, this, _1, _2, _3, &denoising);
|
||||
denoising.functions.divide_shadow = function_bind(&CPUDevice::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
|
||||
denoising.functions.non_local_means = function_bind(&CPUDevice::denoising_non_local_means, this, _1, _2, _3, _4, &denoising);
|
||||
denoising.functions.combine_halves = function_bind(&CPUDevice::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
|
||||
denoising.functions.get_feature = function_bind(&CPUDevice::denoising_get_feature, this, _1, _2, _3, _4, &denoising);
|
||||
denoising.functions.detect_outliers = function_bind(&CPUDevice::denoising_detect_outliers, this, _1, _2, _3, _4, &denoising);
|
||||
denoising.functions.set_tiles = function_bind(&CPUDevice::denoising_set_tiles, this, _1, &denoising);
|
||||
|
||||
denoising.filter_area = make_int4(tile.x, tile.y, tile.w, tile.h);
|
||||
@@ -663,7 +683,7 @@ public:
|
||||
kgbuffer.resize(1);
|
||||
mem_alloc("kernel_globals", kgbuffer, MEM_READ_WRITE);
|
||||
|
||||
KernelGlobals *kg = new((void*)kgbuffer.device_pointer) KernelGlobals(thread_kernel_globals_init());
|
||||
KernelGlobals *kg = new ((void*) kgbuffer.device_pointer) KernelGlobals(thread_kernel_globals_init());
|
||||
|
||||
CPUSplitKernel *split_kernel = NULL;
|
||||
if(use_split_kernel) {
|
||||
@@ -702,6 +722,7 @@ public:
|
||||
}
|
||||
|
||||
thread_kernel_globals_free((KernelGlobals*)kgbuffer.device_pointer);
|
||||
kg->~KernelGlobals();
|
||||
mem_free(kgbuffer);
|
||||
delete split_kernel;
|
||||
}
|
||||
@@ -912,7 +933,8 @@ bool CPUSplitKernel::enqueue_split_kernel_data_init(const KernelDimensions& dim,
|
||||
return true;
|
||||
}
|
||||
|
||||
SplitKernelFunction* CPUSplitKernel::get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&)
|
||||
SplitKernelFunction* CPUSplitKernel::get_split_kernel_function(const string& kernel_name,
|
||||
const DeviceRequestedFeatures&)
|
||||
{
|
||||
CPUSplitKernelFunction *kernel = new CPUSplitKernelFunction(device);
|
||||
|
||||
|
@@ -105,7 +105,8 @@ public:
|
||||
device_memory& use_queues_flag,
|
||||
device_memory& work_pool_wgs);
|
||||
|
||||
virtual SplitKernelFunction* get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&);
|
||||
virtual SplitKernelFunction* get_split_kernel_function(const string& kernel_name,
|
||||
const DeviceRequestedFeatures&);
|
||||
virtual int2 split_kernel_local_size();
|
||||
virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task);
|
||||
};
|
||||
@@ -225,6 +226,9 @@ public:
|
||||
cuDevice = 0;
|
||||
cuContext = 0;
|
||||
|
||||
cuModule = 0;
|
||||
cuFilterModule = 0;
|
||||
|
||||
split_kernel = NULL;
|
||||
|
||||
need_bindless_mapping = false;
|
||||
@@ -487,6 +491,16 @@ public:
|
||||
|
||||
bool load_kernels(const DeviceRequestedFeatures& requested_features)
|
||||
{
|
||||
/* TODO(sergey): Support kernels re-load for CUDA devices.
|
||||
*
|
||||
* Currently re-loading kernel will invalidate memory pointers,
|
||||
* causing problems in cuCtxSynchronize.
|
||||
*/
|
||||
if(cuFilterModule && cuModule) {
|
||||
VLOG(1) << "Skipping kernel reload, not currently supported.";
|
||||
return true;
|
||||
}
|
||||
|
||||
/* check if cuda init succeeded */
|
||||
if(cuContext == 0)
|
||||
return false;
|
||||
@@ -949,7 +963,7 @@ public:
|
||||
cuda_push_context();
|
||||
|
||||
int4 rect = task->rect;
|
||||
int w = rect.z-rect.x;
|
||||
int w = align_up(rect.z-rect.x, 4);
|
||||
int h = rect.w-rect.y;
|
||||
int r = task->nlm_state.r;
|
||||
int f = task->nlm_state.f;
|
||||
@@ -1038,8 +1052,6 @@ public:
|
||||
|
||||
bool denoising_reconstruct(device_ptr color_ptr,
|
||||
device_ptr color_variance_ptr,
|
||||
device_ptr guide_ptr,
|
||||
device_ptr guide_variance_ptr,
|
||||
device_ptr output_ptr,
|
||||
DenoisingTask *task)
|
||||
{
|
||||
@@ -1083,8 +1095,8 @@ public:
|
||||
task->reconstruction_state.source_h - max(0, dy)};
|
||||
|
||||
void *calc_difference_args[] = {&dx, &dy,
|
||||
&guide_ptr,
|
||||
&guide_variance_ptr,
|
||||
&color_ptr,
|
||||
&color_variance_ptr,
|
||||
&difference,
|
||||
&local_rect,
|
||||
&task->buffer.w,
|
||||
@@ -1113,8 +1125,6 @@ public:
|
||||
void *construct_gramian_args[] = {&dx, &dy,
|
||||
&blurDifference,
|
||||
&task->buffer.mem.device_pointer,
|
||||
&color_ptr,
|
||||
&color_variance_ptr,
|
||||
&task->storage.transform.device_pointer,
|
||||
&task->storage.rank.device_pointer,
|
||||
&task->storage.XtWX.device_pointer,
|
||||
@@ -1148,8 +1158,6 @@ public:
|
||||
device_ptr mean_ptr, device_ptr variance_ptr,
|
||||
int r, int4 rect, DenoisingTask *task)
|
||||
{
|
||||
(void) task;
|
||||
|
||||
if(have_error())
|
||||
return false;
|
||||
|
||||
@@ -1179,8 +1187,6 @@ public:
|
||||
device_ptr sample_variance_ptr, device_ptr sv_variance_ptr,
|
||||
device_ptr buffer_variance_ptr, DenoisingTask *task)
|
||||
{
|
||||
(void) task;
|
||||
|
||||
if(have_error())
|
||||
return false;
|
||||
|
||||
@@ -1248,16 +1254,49 @@ public:
|
||||
return !have_error();
|
||||
}
|
||||
|
||||
bool denoising_detect_outliers(device_ptr image_ptr,
|
||||
device_ptr variance_ptr,
|
||||
device_ptr depth_ptr,
|
||||
device_ptr output_ptr,
|
||||
DenoisingTask *task)
|
||||
{
|
||||
if(have_error())
|
||||
return false;
|
||||
|
||||
cuda_push_context();
|
||||
|
||||
CUfunction cuFilterDetectOutliers;
|
||||
cuda_assert(cuModuleGetFunction(&cuFilterDetectOutliers, cuFilterModule, "kernel_cuda_filter_detect_outliers"));
|
||||
cuda_assert(cuFuncSetCacheConfig(cuFilterDetectOutliers, CU_FUNC_CACHE_PREFER_L1));
|
||||
CUDA_GET_BLOCKSIZE(cuFilterDetectOutliers,
|
||||
task->rect.z-task->rect.x,
|
||||
task->rect.w-task->rect.y);
|
||||
|
||||
void *args[] = {&image_ptr,
|
||||
&variance_ptr,
|
||||
&depth_ptr,
|
||||
&output_ptr,
|
||||
&task->rect,
|
||||
&task->buffer.pass_stride};
|
||||
|
||||
CUDA_LAUNCH_KERNEL(cuFilterDetectOutliers, args);
|
||||
cuda_assert(cuCtxSynchronize());
|
||||
|
||||
cuda_pop_context();
|
||||
return !have_error();
|
||||
}
|
||||
|
||||
void denoise(RenderTile &rtile, const DeviceTask &task)
|
||||
{
|
||||
DenoisingTask denoising(this);
|
||||
|
||||
denoising.functions.construct_transform = function_bind(&CUDADevice::denoising_construct_transform, this, &denoising);
|
||||
denoising.functions.reconstruct = function_bind(&CUDADevice::denoising_reconstruct, this, _1, _2, _3, _4, _5, &denoising);
|
||||
denoising.functions.reconstruct = function_bind(&CUDADevice::denoising_reconstruct, this, _1, _2, _3, &denoising);
|
||||
denoising.functions.divide_shadow = function_bind(&CUDADevice::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
|
||||
denoising.functions.non_local_means = function_bind(&CUDADevice::denoising_non_local_means, this, _1, _2, _3, _4, &denoising);
|
||||
denoising.functions.combine_halves = function_bind(&CUDADevice::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
|
||||
denoising.functions.get_feature = function_bind(&CUDADevice::denoising_get_feature, this, _1, _2, _3, _4, &denoising);
|
||||
denoising.functions.detect_outliers = function_bind(&CUDADevice::denoising_detect_outliers, this, _1, _2, _3, _4, &denoising);
|
||||
denoising.functions.set_tiles = function_bind(&CUDADevice::denoising_set_tiles, this, _1, &denoising);
|
||||
|
||||
denoising.filter_area = make_int4(rtile.x, rtile.y, rtile.w, rtile.h);
|
||||
@@ -1999,7 +2038,8 @@ bool CUDASplitKernel::enqueue_split_kernel_data_init(const KernelDimensions& dim
|
||||
return !device->have_error();
|
||||
}
|
||||
|
||||
SplitKernelFunction* CUDASplitKernel::get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&)
|
||||
SplitKernelFunction* CUDASplitKernel::get_split_kernel_function(const string& kernel_name,
|
||||
const DeviceRequestedFeatures&)
|
||||
{
|
||||
CUfunction func;
|
||||
|
||||
|
@@ -139,9 +139,9 @@ bool DenoisingTask::run_denoising()
|
||||
nlm_state.temporary_2_ptr = *nlm_temporary_2;
|
||||
nlm_state.temporary_3_ptr = *nlm_temporary_3;
|
||||
|
||||
int mean_from[] = { 0, 1, 2, 6, 7, 8, 12 };
|
||||
int variance_from[] = { 3, 4, 5, 9, 10, 11, 13 };
|
||||
int pass_to[] = { 1, 2, 3, 0, 5, 6, 7 };
|
||||
int mean_from[] = { 0, 1, 2, 12, 6, 7, 8 };
|
||||
int variance_from[] = { 3, 4, 5, 13, 9, 10, 11};
|
||||
int pass_to[] = { 1, 2, 3, 0, 5, 6, 7};
|
||||
for(int pass = 0; pass < 7; pass++) {
|
||||
device_sub_ptr feature_pass(device, buffer.mem, pass_to[pass]*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
|
||||
/* Get the unfiltered pass and its variance from the RenderBuffers. */
|
||||
@@ -159,11 +159,25 @@ bool DenoisingTask::run_denoising()
|
||||
int mean_to[] = { 8, 9, 10};
|
||||
int variance_to[] = {11, 12, 13};
|
||||
int num_color_passes = 3;
|
||||
|
||||
device_only_memory<float> temp_color;
|
||||
temp_color.resize(3*buffer.pass_stride);
|
||||
device->mem_alloc("Denoising temporary color", temp_color, MEM_READ_WRITE);
|
||||
|
||||
for(int pass = 0; pass < num_color_passes; pass++) {
|
||||
device_sub_ptr color_pass (device, buffer.mem, mean_to[pass]*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
|
||||
device_sub_ptr color_pass(device, temp_color, pass*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
|
||||
device_sub_ptr color_var_pass(device, buffer.mem, variance_to[pass]*buffer.pass_stride, buffer.pass_stride, MEM_READ_WRITE);
|
||||
functions.get_feature(mean_from[pass], variance_from[pass], *color_pass, *color_var_pass);
|
||||
}
|
||||
|
||||
{
|
||||
device_sub_ptr depth_pass (device, buffer.mem, 0, buffer.pass_stride, MEM_READ_WRITE);
|
||||
device_sub_ptr color_var_pass(device, buffer.mem, variance_to[0]*buffer.pass_stride, 3*buffer.pass_stride, MEM_READ_WRITE);
|
||||
device_sub_ptr output_pass (device, buffer.mem, mean_to[0]*buffer.pass_stride, 3*buffer.pass_stride, MEM_READ_WRITE);
|
||||
functions.detect_outliers(temp_color.device_pointer, *color_var_pass, *depth_pass, *output_pass);
|
||||
}
|
||||
|
||||
device->mem_free(temp_color);
|
||||
}
|
||||
|
||||
storage.w = filter_area.z;
|
||||
@@ -201,7 +215,7 @@ bool DenoisingTask::run_denoising()
|
||||
{
|
||||
device_sub_ptr color_ptr (device, buffer.mem, 8*buffer.pass_stride, 3*buffer.pass_stride, MEM_READ_WRITE);
|
||||
device_sub_ptr color_var_ptr(device, buffer.mem, 11*buffer.pass_stride, 3*buffer.pass_stride, MEM_READ_WRITE);
|
||||
functions.reconstruct(*color_ptr, *color_var_ptr, *color_ptr, *color_var_ptr, render_buffer.ptr);
|
||||
functions.reconstruct(*color_ptr, *color_var_ptr, render_buffer.ptr);
|
||||
}
|
||||
|
||||
device->mem_free(storage.XtWX);
|
||||
|
@@ -58,8 +58,6 @@ public:
|
||||
)> non_local_means;
|
||||
function<bool(device_ptr color_ptr,
|
||||
device_ptr color_variance_ptr,
|
||||
device_ptr guide_ptr,
|
||||
device_ptr guide_variance_ptr,
|
||||
device_ptr output_ptr
|
||||
)> reconstruct;
|
||||
function<bool()> construct_transform;
|
||||
@@ -82,6 +80,11 @@ public:
|
||||
device_ptr mean_ptr,
|
||||
device_ptr variance_ptr
|
||||
)> get_feature;
|
||||
function<bool(device_ptr image_ptr,
|
||||
device_ptr variance_ptr,
|
||||
device_ptr depth_ptr,
|
||||
device_ptr output_ptr
|
||||
)> detect_outliers;
|
||||
function<bool(device_ptr*)> set_tiles;
|
||||
} functions;
|
||||
|
||||
|
@@ -335,7 +335,7 @@ public:
|
||||
device_ptr original_ptr = mem.device_pointer;
|
||||
mem.device_pointer = tiles[i].buffer;
|
||||
|
||||
/* Copy denoised tile to the host device. */
|
||||
/* Copy denoised tile to the host. */
|
||||
if(i == 4) {
|
||||
tiles[i].buffers->copy_from_device(sub_device);
|
||||
}
|
||||
|
@@ -130,10 +130,22 @@ string device_opencl_capabilities(void)
|
||||
opencl_assert(func(id, what, sizeof(data), &data, NULL)); \
|
||||
result += string_printf("%s: %s\n", name, data); \
|
||||
} while(false)
|
||||
#define APPEND_STRING_EXTENSION_INFO(func, id, name, what) \
|
||||
do { \
|
||||
char data[1024] = "\0"; \
|
||||
size_t length = 0; \
|
||||
if(func(id, what, sizeof(data), &data, &length) == CL_SUCCESS) { \
|
||||
if(length != 0 && data[0] != '\0') { \
|
||||
result += string_printf("%s: %s\n", name, data); \
|
||||
} \
|
||||
} \
|
||||
} while(false)
|
||||
#define APPEND_PLATFORM_STRING_INFO(id, name, what) \
|
||||
APPEND_STRING_INFO(clGetPlatformInfo, id, "\tPlatform " name, what)
|
||||
#define APPEND_DEVICE_STRING_INFO(id, name, what) \
|
||||
APPEND_STRING_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what)
|
||||
#define APPEND_DEVICE_STRING_EXTENSION_INFO(id, name, what) \
|
||||
APPEND_STRING_EXTENSION_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what)
|
||||
|
||||
vector<cl_device_id> device_ids;
|
||||
for(cl_uint platform = 0; platform < num_platforms; ++platform) {
|
||||
@@ -167,6 +179,7 @@ string device_opencl_capabilities(void)
|
||||
result += string_printf("\t\tDevice: #%u\n", device);
|
||||
|
||||
APPEND_DEVICE_STRING_INFO(device_id, "Name", CL_DEVICE_NAME);
|
||||
APPEND_DEVICE_STRING_EXTENSION_INFO(device_id, "Board Name", CL_DEVICE_BOARD_NAME_AMD);
|
||||
APPEND_DEVICE_STRING_INFO(device_id, "Vendor", CL_DEVICE_VENDOR);
|
||||
APPEND_DEVICE_STRING_INFO(device_id, "OpenCL C Version", CL_DEVICE_OPENCL_C_VERSION);
|
||||
APPEND_DEVICE_STRING_INFO(device_id, "Profile", CL_DEVICE_PROFILE);
|
||||
|
@@ -47,6 +47,7 @@ DeviceSplitKernel::DeviceSplitKernel(Device *device) : device(device)
|
||||
kernel_direct_lighting = NULL;
|
||||
kernel_shadow_blocked_ao = NULL;
|
||||
kernel_shadow_blocked_dl = NULL;
|
||||
kernel_enqueue_inactive = NULL;
|
||||
kernel_next_iteration_setup = NULL;
|
||||
kernel_indirect_subsurface = NULL;
|
||||
kernel_buffer_update = NULL;
|
||||
@@ -74,6 +75,7 @@ DeviceSplitKernel::~DeviceSplitKernel()
|
||||
delete kernel_direct_lighting;
|
||||
delete kernel_shadow_blocked_ao;
|
||||
delete kernel_shadow_blocked_dl;
|
||||
delete kernel_enqueue_inactive;
|
||||
delete kernel_next_iteration_setup;
|
||||
delete kernel_indirect_subsurface;
|
||||
delete kernel_buffer_update;
|
||||
@@ -101,6 +103,7 @@ bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures& requested_fe
|
||||
LOAD_KERNEL(direct_lighting);
|
||||
LOAD_KERNEL(shadow_blocked_ao);
|
||||
LOAD_KERNEL(shadow_blocked_dl);
|
||||
LOAD_KERNEL(enqueue_inactive);
|
||||
LOAD_KERNEL(next_iteration_setup);
|
||||
LOAD_KERNEL(indirect_subsurface);
|
||||
LOAD_KERNEL(buffer_update);
|
||||
@@ -256,6 +259,7 @@ bool DeviceSplitKernel::path_trace(DeviceTask *task,
|
||||
ENQUEUE_SPLIT_KERNEL(direct_lighting, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(shadow_blocked_ao, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(shadow_blocked_dl, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(enqueue_inactive, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(next_iteration_setup, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(indirect_subsurface, global_size, local_size);
|
||||
ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
|
||||
|
@@ -69,6 +69,7 @@ private:
|
||||
SplitKernelFunction *kernel_direct_lighting;
|
||||
SplitKernelFunction *kernel_shadow_blocked_ao;
|
||||
SplitKernelFunction *kernel_shadow_blocked_dl;
|
||||
SplitKernelFunction *kernel_enqueue_inactive;
|
||||
SplitKernelFunction *kernel_next_iteration_setup;
|
||||
SplitKernelFunction *kernel_indirect_subsurface;
|
||||
SplitKernelFunction *kernel_buffer_update;
|
||||
@@ -124,7 +125,8 @@ public:
|
||||
device_memory& use_queues_flag,
|
||||
device_memory& work_pool_wgs) = 0;
|
||||
|
||||
virtual SplitKernelFunction* get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&) = 0;
|
||||
virtual SplitKernelFunction* get_split_kernel_function(const string& kernel_name,
|
||||
const DeviceRequestedFeatures&) = 0;
|
||||
virtual int2 split_kernel_local_size() = 0;
|
||||
virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task) = 0;
|
||||
};
|
||||
|
@@ -27,6 +27,9 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Disable workarounds, seems to be working fine on latest drivers. */
|
||||
#define CYCLES_DISABLE_DRIVER_WORKAROUNDS
|
||||
|
||||
/* Define CYCLES_DISABLE_DRIVER_WORKAROUNDS to disable workaounds for testing */
|
||||
#ifndef CYCLES_DISABLE_DRIVER_WORKAROUNDS
|
||||
/* Work around AMD driver hangs by ensuring each command is finished before doing anything else. */
|
||||
@@ -84,7 +87,7 @@ public:
|
||||
string *error = NULL);
|
||||
static bool device_version_check(cl_device_id device,
|
||||
string *error = NULL);
|
||||
static string get_hardware_id(string platform_name,
|
||||
static string get_hardware_id(const string& platform_name,
|
||||
cl_device_id device_id);
|
||||
static void get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices,
|
||||
bool force_all = false);
|
||||
@@ -130,6 +133,11 @@ public:
|
||||
cl_int* error = NULL);
|
||||
static cl_device_type get_device_type(cl_device_id device_id);
|
||||
|
||||
static bool get_driver_version(cl_device_id device_id,
|
||||
int *major,
|
||||
int *minor,
|
||||
cl_int* error = NULL);
|
||||
|
||||
static int mem_address_alignment(cl_device_id device_id);
|
||||
|
||||
/* Get somewhat more readable device name.
|
||||
@@ -242,17 +250,17 @@ public:
|
||||
public:
|
||||
OpenCLProgram() : loaded(false), device(NULL) {}
|
||||
OpenCLProgram(OpenCLDeviceBase *device,
|
||||
string program_name,
|
||||
string kernel_name,
|
||||
string kernel_build_options,
|
||||
const string& program_name,
|
||||
const string& kernel_name,
|
||||
const string& kernel_build_options,
|
||||
bool use_stdout = true);
|
||||
~OpenCLProgram();
|
||||
|
||||
void add_kernel(ustring name);
|
||||
void load();
|
||||
|
||||
bool is_loaded() { return loaded; }
|
||||
string get_log() { return log; }
|
||||
bool is_loaded() const { return loaded; }
|
||||
const string& get_log() const { return log; }
|
||||
void report_error();
|
||||
|
||||
cl_kernel operator()();
|
||||
@@ -266,8 +274,8 @@ public:
|
||||
bool load_binary(const string& clbin, const string *debug_src = NULL);
|
||||
bool save_binary(const string& clbin);
|
||||
|
||||
void add_log(string msg, bool is_debug);
|
||||
void add_error(string msg);
|
||||
void add_log(const string& msg, bool is_debug);
|
||||
void add_error(const string& msg);
|
||||
|
||||
bool loaded;
|
||||
cl_program program;
|
||||
@@ -390,8 +398,6 @@ protected:
|
||||
bool denoising_construct_transform(DenoisingTask *task);
|
||||
bool denoising_reconstruct(device_ptr color_ptr,
|
||||
device_ptr color_variance_ptr,
|
||||
device_ptr guide_ptr,
|
||||
device_ptr guide_variance_ptr,
|
||||
device_ptr output_ptr,
|
||||
DenoisingTask *task);
|
||||
bool denoising_combine_halves(device_ptr a_ptr,
|
||||
@@ -411,6 +417,11 @@ protected:
|
||||
device_ptr mean_ptr,
|
||||
device_ptr variance_ptr,
|
||||
DenoisingTask *task);
|
||||
bool denoising_detect_outliers(device_ptr image_ptr,
|
||||
device_ptr variance_ptr,
|
||||
device_ptr depth_ptr,
|
||||
device_ptr output_ptr,
|
||||
DenoisingTask *task);
|
||||
bool denoising_set_tiles(device_ptr *buffers,
|
||||
DenoisingTask *task);
|
||||
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "kernel/kernel_types.h"
|
||||
|
||||
#include "util/util_algorithm.h"
|
||||
#include "util/util_foreach.h"
|
||||
#include "util/util_logging.h"
|
||||
#include "util/util_md5.h"
|
||||
@@ -216,6 +217,7 @@ bool OpenCLDeviceBase::load_kernels(const DeviceRequestedFeatures& requested_fea
|
||||
denoising_program = OpenCLProgram(this, "denoising", "filter.cl", "");
|
||||
denoising_program.add_kernel(ustring("filter_divide_shadow"));
|
||||
denoising_program.add_kernel(ustring("filter_get_feature"));
|
||||
denoising_program.add_kernel(ustring("filter_detect_outliers"));
|
||||
denoising_program.add_kernel(ustring("filter_combine_halves"));
|
||||
denoising_program.add_kernel(ustring("filter_construct_transform"));
|
||||
denoising_program.add_kernel(ustring("filter_nlm_calc_difference"));
|
||||
@@ -275,6 +277,25 @@ void OpenCLDeviceBase::mem_alloc(const char *name, device_memory& mem, MemoryTyp
|
||||
|
||||
size_t size = mem.memory_size();
|
||||
|
||||
/* check there is enough memory available for the allocation */
|
||||
cl_ulong max_alloc_size = 0;
|
||||
clGetDeviceInfo(cdDevice, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_alloc_size, NULL);
|
||||
|
||||
if(DebugFlags().opencl.mem_limit) {
|
||||
max_alloc_size = min(max_alloc_size,
|
||||
cl_ulong(DebugFlags().opencl.mem_limit - stats.mem_used));
|
||||
}
|
||||
|
||||
if(size > max_alloc_size) {
|
||||
string error = "Scene too complex to fit in available memory.";
|
||||
if(name != NULL) {
|
||||
error += string_printf(" (allocating buffer %s failed.)", name);
|
||||
}
|
||||
set_error(error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
cl_mem_flags mem_flag;
|
||||
void *mem_ptr = NULL;
|
||||
|
||||
@@ -692,8 +713,6 @@ bool OpenCLDeviceBase::denoising_construct_transform(DenoisingTask *task)
|
||||
|
||||
bool OpenCLDeviceBase::denoising_reconstruct(device_ptr color_ptr,
|
||||
device_ptr color_variance_ptr,
|
||||
device_ptr guide_ptr,
|
||||
device_ptr guide_variance_ptr,
|
||||
device_ptr output_ptr,
|
||||
DenoisingTask *task)
|
||||
{
|
||||
@@ -702,8 +721,6 @@ bool OpenCLDeviceBase::denoising_reconstruct(device_ptr color_ptr,
|
||||
|
||||
cl_mem color_mem = CL_MEM_PTR(color_ptr);
|
||||
cl_mem color_variance_mem = CL_MEM_PTR(color_variance_ptr);
|
||||
cl_mem guide_mem = CL_MEM_PTR(guide_ptr);
|
||||
cl_mem guide_variance_mem = CL_MEM_PTR(guide_variance_ptr);
|
||||
cl_mem output_mem = CL_MEM_PTR(output_ptr);
|
||||
|
||||
cl_mem buffer_mem = CL_MEM_PTR(task->buffer.mem.device_pointer);
|
||||
@@ -734,8 +751,8 @@ bool OpenCLDeviceBase::denoising_reconstruct(device_ptr color_ptr,
|
||||
|
||||
kernel_set_args(ckNLMCalcDifference, 0,
|
||||
dx, dy,
|
||||
guide_mem,
|
||||
guide_variance_mem,
|
||||
color_mem,
|
||||
color_variance_mem,
|
||||
difference,
|
||||
local_rect,
|
||||
task->buffer.w,
|
||||
@@ -774,8 +791,6 @@ bool OpenCLDeviceBase::denoising_reconstruct(device_ptr color_ptr,
|
||||
dx, dy,
|
||||
blurDifference,
|
||||
buffer_mem,
|
||||
color_mem,
|
||||
color_variance_mem,
|
||||
transform_mem,
|
||||
rank_mem,
|
||||
XtWX_mem,
|
||||
@@ -816,8 +831,6 @@ bool OpenCLDeviceBase::denoising_combine_halves(device_ptr a_ptr,
|
||||
int r, int4 rect,
|
||||
DenoisingTask *task)
|
||||
{
|
||||
(void) task;
|
||||
|
||||
cl_mem a_mem = CL_MEM_PTR(a_ptr);
|
||||
cl_mem b_mem = CL_MEM_PTR(b_ptr);
|
||||
cl_mem mean_mem = CL_MEM_PTR(mean_ptr);
|
||||
@@ -846,8 +859,6 @@ bool OpenCLDeviceBase::denoising_divide_shadow(device_ptr a_ptr,
|
||||
device_ptr buffer_variance_ptr,
|
||||
DenoisingTask *task)
|
||||
{
|
||||
(void) task;
|
||||
|
||||
cl_mem a_mem = CL_MEM_PTR(a_ptr);
|
||||
cl_mem b_mem = CL_MEM_PTR(b_ptr);
|
||||
cl_mem sample_variance_mem = CL_MEM_PTR(sample_variance_ptr);
|
||||
@@ -910,6 +921,33 @@ bool OpenCLDeviceBase::denoising_get_feature(int mean_offset,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenCLDeviceBase::denoising_detect_outliers(device_ptr image_ptr,
|
||||
device_ptr variance_ptr,
|
||||
device_ptr depth_ptr,
|
||||
device_ptr output_ptr,
|
||||
DenoisingTask *task)
|
||||
{
|
||||
cl_mem image_mem = CL_MEM_PTR(image_ptr);
|
||||
cl_mem variance_mem = CL_MEM_PTR(variance_ptr);
|
||||
cl_mem depth_mem = CL_MEM_PTR(depth_ptr);
|
||||
cl_mem output_mem = CL_MEM_PTR(output_ptr);
|
||||
|
||||
cl_kernel ckFilterDetectOutliers = denoising_program(ustring("filter_detect_outliers"));
|
||||
|
||||
kernel_set_args(ckFilterDetectOutliers, 0,
|
||||
image_mem,
|
||||
variance_mem,
|
||||
depth_mem,
|
||||
output_mem,
|
||||
task->rect,
|
||||
task->buffer.pass_stride);
|
||||
enqueue_kernel(ckFilterDetectOutliers,
|
||||
task->rect.z-task->rect.x,
|
||||
task->rect.w-task->rect.y);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenCLDeviceBase::denoising_set_tiles(device_ptr *buffers,
|
||||
DenoisingTask *task)
|
||||
{
|
||||
@@ -937,11 +975,12 @@ void OpenCLDeviceBase::denoise(RenderTile &rtile, const DeviceTask &task)
|
||||
|
||||
denoising.functions.set_tiles = function_bind(&OpenCLDeviceBase::denoising_set_tiles, this, _1, &denoising);
|
||||
denoising.functions.construct_transform = function_bind(&OpenCLDeviceBase::denoising_construct_transform, this, &denoising);
|
||||
denoising.functions.reconstruct = function_bind(&OpenCLDeviceBase::denoising_reconstruct, this, _1, _2, _3, _4, _5, &denoising);
|
||||
denoising.functions.reconstruct = function_bind(&OpenCLDeviceBase::denoising_reconstruct, this, _1, _2, _3, &denoising);
|
||||
denoising.functions.divide_shadow = function_bind(&OpenCLDeviceBase::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
|
||||
denoising.functions.non_local_means = function_bind(&OpenCLDeviceBase::denoising_non_local_means, this, _1, _2, _3, _4, &denoising);
|
||||
denoising.functions.combine_halves = function_bind(&OpenCLDeviceBase::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
|
||||
denoising.functions.get_feature = function_bind(&OpenCLDeviceBase::denoising_get_feature, this, _1, _2, _3, _4, &denoising);
|
||||
denoising.functions.detect_outliers = function_bind(&OpenCLDeviceBase::denoising_detect_outliers, this, _1, _2, _3, _4, &denoising);
|
||||
|
||||
denoising.filter_area = make_int4(rtile.x, rtile.y, rtile.w, rtile.h);
|
||||
denoising.render_buffer.samples = rtile.sample;
|
||||
@@ -1207,7 +1246,7 @@ void OpenCLDeviceBase::store_cached_kernel(
|
||||
}
|
||||
|
||||
string OpenCLDeviceBase::build_options_for_base_program(
|
||||
const DeviceRequestedFeatures& /*requested_features*/)
|
||||
const DeviceRequestedFeatures& requested_features)
|
||||
{
|
||||
/* TODO(sergey): By default we compile all features, meaning
|
||||
* mega kernel is not getting feature-based optimizations.
|
||||
@@ -1215,6 +1254,14 @@ string OpenCLDeviceBase::build_options_for_base_program(
|
||||
* Ideally we need always compile kernel with as less features
|
||||
* enabled as possible to keep performance at it's max.
|
||||
*/
|
||||
|
||||
/* For now disable baking when not in use as this has major
|
||||
* impact on kernel build times.
|
||||
*/
|
||||
if(!requested_features.use_baking) {
|
||||
return "-D__NO_BAKING__";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "device/device_split_kernel.h"
|
||||
|
||||
#include "util/util_algorithm.h"
|
||||
#include "util/util_logging.h"
|
||||
#include "util/util_md5.h"
|
||||
#include "util/util_path.h"
|
||||
@@ -70,6 +71,10 @@ public:
|
||||
delete split_kernel;
|
||||
}
|
||||
|
||||
virtual bool show_samples() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool load_kernels(const DeviceRequestedFeatures& requested_features,
|
||||
vector<OpenCLDeviceBase::OpenCLProgram*> &programs)
|
||||
{
|
||||
@@ -172,17 +177,62 @@ protected:
|
||||
friend class OpenCLSplitKernelFunction;
|
||||
};
|
||||
|
||||
struct CachedSplitMemory {
|
||||
int id;
|
||||
device_memory *split_data;
|
||||
device_memory *ray_state;
|
||||
device_ptr *rng_state;
|
||||
device_memory *queue_index;
|
||||
device_memory *use_queues_flag;
|
||||
device_memory *work_pools;
|
||||
device_ptr *buffer;
|
||||
};
|
||||
|
||||
class OpenCLSplitKernelFunction : public SplitKernelFunction {
|
||||
public:
|
||||
OpenCLDeviceSplitKernel* device;
|
||||
OpenCLDeviceBase::OpenCLProgram program;
|
||||
CachedSplitMemory& cached_memory;
|
||||
int cached_id;
|
||||
|
||||
OpenCLSplitKernelFunction(OpenCLDeviceSplitKernel* device) : device(device) {}
|
||||
~OpenCLSplitKernelFunction() { program.release(); }
|
||||
OpenCLSplitKernelFunction(OpenCLDeviceSplitKernel* device, CachedSplitMemory& cached_memory) :
|
||||
device(device), cached_memory(cached_memory), cached_id(cached_memory.id-1)
|
||||
{
|
||||
}
|
||||
|
||||
~OpenCLSplitKernelFunction()
|
||||
{
|
||||
program.release();
|
||||
}
|
||||
|
||||
virtual bool enqueue(const KernelDimensions& dim, device_memory& kg, device_memory& data)
|
||||
{
|
||||
device->kernel_set_args(program(), 0, kg, data);
|
||||
if(cached_id != cached_memory.id) {
|
||||
cl_uint start_arg_index =
|
||||
device->kernel_set_args(program(),
|
||||
0,
|
||||
kg,
|
||||
data,
|
||||
*cached_memory.split_data,
|
||||
*cached_memory.ray_state,
|
||||
*cached_memory.rng_state);
|
||||
|
||||
/* TODO(sergey): Avoid map lookup here. */
|
||||
#define KERNEL_TEX(type, ttype, name) \
|
||||
device->set_kernel_arg_mem(program(), &start_arg_index, #name);
|
||||
#include "kernel/kernel_textures.h"
|
||||
#undef KERNEL_TEX
|
||||
|
||||
start_arg_index +=
|
||||
device->kernel_set_args(program(),
|
||||
start_arg_index,
|
||||
*cached_memory.queue_index,
|
||||
*cached_memory.use_queues_flag,
|
||||
*cached_memory.work_pools,
|
||||
*cached_memory.buffer);
|
||||
|
||||
cached_id = cached_memory.id;
|
||||
}
|
||||
|
||||
device->ciErr = clEnqueueNDRangeKernel(device->cqCommandQueue,
|
||||
program(),
|
||||
@@ -209,14 +259,15 @@ public:
|
||||
|
||||
class OpenCLSplitKernel : public DeviceSplitKernel {
|
||||
OpenCLDeviceSplitKernel *device;
|
||||
CachedSplitMemory cached_memory;
|
||||
public:
|
||||
explicit OpenCLSplitKernel(OpenCLDeviceSplitKernel *device) : DeviceSplitKernel(device), device(device) {
|
||||
}
|
||||
|
||||
virtual SplitKernelFunction* get_split_kernel_function(string kernel_name,
|
||||
virtual SplitKernelFunction* get_split_kernel_function(const string& kernel_name,
|
||||
const DeviceRequestedFeatures& requested_features)
|
||||
{
|
||||
OpenCLSplitKernelFunction* kernel = new OpenCLSplitKernelFunction(device);
|
||||
OpenCLSplitKernelFunction* kernel = new OpenCLSplitKernelFunction(device, cached_memory);
|
||||
|
||||
bool single_program = OpenCLInfo::use_single_program();
|
||||
kernel->program =
|
||||
@@ -345,6 +396,15 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
cached_memory.split_data = &split_data;
|
||||
cached_memory.ray_state = &ray_state;
|
||||
cached_memory.rng_state = &rtile.rng_state;
|
||||
cached_memory.queue_index = &queue_index;
|
||||
cached_memory.use_queues_flag = &use_queues_flag;
|
||||
cached_memory.work_pools = &work_pool_wgs;
|
||||
cached_memory.buffer = &rtile.buffer;
|
||||
cached_memory.id++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -364,12 +424,18 @@ public:
|
||||
|
||||
cl_ulong max_buffer_size;
|
||||
clGetDeviceInfo(device->cdDevice, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_buffer_size, NULL);
|
||||
|
||||
if(DebugFlags().opencl.mem_limit) {
|
||||
max_buffer_size = min(max_buffer_size,
|
||||
cl_ulong(DebugFlags().opencl.mem_limit - device->stats.mem_used));
|
||||
}
|
||||
|
||||
VLOG(1) << "Maximum device allocation size: "
|
||||
<< string_human_readable_number(max_buffer_size) << " bytes. ("
|
||||
<< string_human_readable_size(max_buffer_size) << ").";
|
||||
|
||||
size_t num_elements = max_elements_for_max_buffer_size(kg, data, max_buffer_size / 2);
|
||||
int2 global_size = make_int2(round_down((int)sqrt(num_elements), 64), (int)sqrt(num_elements));
|
||||
int2 global_size = make_int2(max(round_down((int)sqrt(num_elements), 64), 64), (int)sqrt(num_elements));
|
||||
VLOG(1) << "Global size: " << global_size << ".";
|
||||
return global_size;
|
||||
}
|
||||
|
@@ -241,9 +241,9 @@ string OpenCLCache::get_kernel_md5()
|
||||
}
|
||||
|
||||
OpenCLDeviceBase::OpenCLProgram::OpenCLProgram(OpenCLDeviceBase *device,
|
||||
string program_name,
|
||||
string kernel_file,
|
||||
string kernel_build_options,
|
||||
const string& program_name,
|
||||
const string& kernel_file,
|
||||
const string& kernel_build_options,
|
||||
bool use_stdout)
|
||||
: device(device),
|
||||
program_name(program_name),
|
||||
@@ -274,7 +274,7 @@ void OpenCLDeviceBase::OpenCLProgram::release()
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCLDeviceBase::OpenCLProgram::add_log(string msg, bool debug)
|
||||
void OpenCLDeviceBase::OpenCLProgram::add_log(const string& msg, bool debug)
|
||||
{
|
||||
if(!use_stdout) {
|
||||
log += msg + "\n";
|
||||
@@ -288,7 +288,7 @@ void OpenCLDeviceBase::OpenCLProgram::add_log(string msg, bool debug)
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCLDeviceBase::OpenCLProgram::add_error(string msg)
|
||||
void OpenCLDeviceBase::OpenCLProgram::add_error(const string& msg)
|
||||
{
|
||||
if(use_stdout) {
|
||||
fprintf(stderr, "%s\n", msg.c_str());
|
||||
@@ -608,6 +608,14 @@ bool OpenCLInfo::device_supported(const string& platform_name,
|
||||
if(!get_device_name(device_id, &device_name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int driver_major = 0;
|
||||
int driver_minor = 0;
|
||||
if(!get_driver_version(device_id, &driver_major, &driver_minor)) {
|
||||
return false;
|
||||
}
|
||||
VLOG(3) << "OpenCL driver version " << driver_major << "." << driver_minor;
|
||||
|
||||
/* It is possible tyo have Iris GPU on AMD/Apple OpenCL framework
|
||||
* (aka, it will not be on Intel framework). This isn't supported
|
||||
* and needs an explicit blacklist.
|
||||
@@ -618,6 +626,21 @@ bool OpenCLInfo::device_supported(const string& platform_name,
|
||||
if(platform_name == "AMD Accelerated Parallel Processing" &&
|
||||
device_type == CL_DEVICE_TYPE_GPU)
|
||||
{
|
||||
if(driver_major < 2236) {
|
||||
VLOG(1) << "AMD driver version " << driver_major << "." << driver_minor << " not supported.";
|
||||
return false;
|
||||
}
|
||||
const char *blacklist[] = {
|
||||
/* GCN 1 */
|
||||
"Tahiti", "Pitcairn", "Capeverde", "Oland",
|
||||
NULL
|
||||
};
|
||||
for (int i = 0; blacklist[i] != NULL; i++) {
|
||||
if(device_name == blacklist[i]) {
|
||||
VLOG(1) << "AMD device " << device_name << " not supported";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if(platform_name == "Apple" && device_type == CL_DEVICE_TYPE_GPU) {
|
||||
@@ -684,7 +707,7 @@ bool OpenCLInfo::device_version_check(cl_device_id device,
|
||||
return true;
|
||||
}
|
||||
|
||||
string OpenCLInfo::get_hardware_id(string platform_name, cl_device_id device_id)
|
||||
string OpenCLInfo::get_hardware_id(const string& platform_name, cl_device_id device_id)
|
||||
{
|
||||
if(platform_name == "AMD Accelerated Parallel Processing" || platform_name == "Apple") {
|
||||
/* Use cl_amd_device_topology extension. */
|
||||
@@ -1063,7 +1086,7 @@ string OpenCLInfo::get_readable_device_name(cl_device_id device_id)
|
||||
CL_DEVICE_BOARD_NAME_AMD,
|
||||
sizeof(board_name),
|
||||
&board_name,
|
||||
&length) == CL_SUCCESS)
|
||||
&length) == CL_SUCCESS)
|
||||
{
|
||||
if(length != 0 && board_name[0] != '\0') {
|
||||
return board_name;
|
||||
@@ -1073,6 +1096,34 @@ string OpenCLInfo::get_readable_device_name(cl_device_id device_id)
|
||||
return get_device_name(device_id);
|
||||
}
|
||||
|
||||
bool OpenCLInfo::get_driver_version(cl_device_id device_id,
|
||||
int *major,
|
||||
int *minor,
|
||||
cl_int* error)
|
||||
{
|
||||
char buffer[1024];
|
||||
cl_int err;
|
||||
if((err = clGetDeviceInfo(device_id,
|
||||
CL_DRIVER_VERSION,
|
||||
sizeof(buffer),
|
||||
&buffer,
|
||||
NULL)) != CL_SUCCESS)
|
||||
{
|
||||
if(error != NULL) {
|
||||
*error = err;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if(error != NULL) {
|
||||
*error = CL_SUCCESS;
|
||||
}
|
||||
if(sscanf(buffer, "%d.%d", major, minor) < 2) {
|
||||
VLOG(1) << string_printf("OpenCL: failed to parse driver version string (%s).", buffer);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int OpenCLInfo::mem_address_alignment(cl_device_id device_id)
|
||||
{
|
||||
int base_align_bits;
|
||||
|
@@ -45,6 +45,7 @@ set(SRC
|
||||
kernels/opencl/kernel_direct_lighting.cl
|
||||
kernels/opencl/kernel_shadow_blocked_ao.cl
|
||||
kernels/opencl/kernel_shadow_blocked_dl.cl
|
||||
kernels/opencl/kernel_enqueue_inactive.cl
|
||||
kernels/opencl/kernel_next_iteration_setup.cl
|
||||
kernels/opencl/kernel_indirect_subsurface.cl
|
||||
kernels/opencl/kernel_buffer_update.cl
|
||||
@@ -121,6 +122,10 @@ set(SRC_KERNELS_CUDA_HEADERS
|
||||
kernels/cuda/kernel_config.h
|
||||
)
|
||||
|
||||
set(SRC_KERNELS_OPENCL_HEADERS
|
||||
kernels/opencl/kernel_split_function.h
|
||||
)
|
||||
|
||||
set(SRC_CLOSURE_HEADERS
|
||||
closure/alloc.h
|
||||
closure/bsdf.h
|
||||
@@ -278,6 +283,7 @@ set(SRC_SPLIT_HEADERS
|
||||
split/kernel_data_init.h
|
||||
split/kernel_direct_lighting.h
|
||||
split/kernel_do_volume.h
|
||||
split/kernel_enqueue_inactive.h
|
||||
split/kernel_holdout_emission_blurring_pathtermination_ao.h
|
||||
split/kernel_indirect_background.h
|
||||
split/kernel_indirect_subsurface.h
|
||||
@@ -450,6 +456,7 @@ add_library(cycles_kernel
|
||||
${SRC_HEADERS}
|
||||
${SRC_KERNELS_CPU_HEADERS}
|
||||
${SRC_KERNELS_CUDA_HEADERS}
|
||||
${SRC_KERNELS_OPENCL_HEADERS}
|
||||
${SRC_BVH_HEADERS}
|
||||
${SRC_CLOSURE_HEADERS}
|
||||
${SRC_FILTER_HEADERS}
|
||||
@@ -490,9 +497,11 @@ delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_subsurface_sc
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_direct_lighting.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shadow_blocked_ao.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shadow_blocked_dl.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_enqueue_inactive.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_next_iteration_setup.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_indirect_subsurface.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_buffer_update.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_split_function.h" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/filter.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/cuda/kernel.cu" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/cuda)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/cuda/kernel_split.cu" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/cuda)
|
||||
|
@@ -423,6 +423,11 @@ ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b)
|
||||
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
||||
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
||||
return bsdf_hair_merge(a, b);
|
||||
#ifdef __PRINCIPLED__
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
|
||||
return bsdf_principled_diffuse_merge(a, b);
|
||||
#endif
|
||||
#ifdef __VOLUME__
|
||||
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
|
||||
return volume_henyey_greenstein_merge(a, b);
|
||||
|
@@ -288,12 +288,16 @@ ccl_device int bsdf_microfacet_ggx_setup(MicrofacetBsdf *bsdf)
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf)
|
||||
ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
|
||||
{
|
||||
bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
|
||||
bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
|
||||
bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
|
||||
|
||||
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
|
||||
float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
|
||||
bsdf->sample_weight *= F;
|
||||
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
@@ -302,12 +306,16 @@ ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf)
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_clearcoat_setup(MicrofacetBsdf *bsdf)
|
||||
ccl_device int bsdf_microfacet_ggx_clearcoat_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
|
||||
{
|
||||
bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
|
||||
bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
|
||||
bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
|
||||
|
||||
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
|
||||
float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
|
||||
bsdf->sample_weight *= 0.25f * bsdf->extra->clearcoat * F;
|
||||
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
@@ -343,12 +351,16 @@ ccl_device int bsdf_microfacet_ggx_aniso_setup(MicrofacetBsdf *bsdf)
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf)
|
||||
ccl_device int bsdf_microfacet_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
|
||||
{
|
||||
bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
|
||||
bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
|
||||
bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
|
||||
|
||||
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
|
||||
float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
|
||||
bsdf->sample_weight *= F;
|
||||
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = saturate(bsdf->alpha_y);
|
||||
|
||||
|
@@ -40,20 +40,20 @@ ccl_device_forceinline float D_ggx_aniso(const float3 wm, const float2 alpha)
|
||||
}
|
||||
|
||||
/* Sample slope distribution (based on page 14 of the supplemental implementation). */
|
||||
ccl_device_forceinline float2 mf_sampleP22_11(const float cosI, const float2 randU)
|
||||
ccl_device_forceinline float2 mf_sampleP22_11(const float cosI, const float randx, const float randy)
|
||||
{
|
||||
if(cosI > 0.9999f || fabsf(cosI) < 1e-6f) {
|
||||
const float r = sqrtf(randU.x / max(1.0f - randU.x, 1e-7f));
|
||||
const float phi = M_2PI_F * randU.y;
|
||||
const float r = sqrtf(randx / max(1.0f - randx, 1e-7f));
|
||||
const float phi = M_2PI_F * randy;
|
||||
return make_float2(r*cosf(phi), r*sinf(phi));
|
||||
}
|
||||
|
||||
const float sinI = sqrtf(1.0f - cosI*cosI);
|
||||
const float sinI = safe_sqrtf(1.0f - cosI*cosI);
|
||||
const float tanI = sinI/cosI;
|
||||
const float projA = 0.5f * (cosI + 1.0f);
|
||||
if(projA < 0.0001f)
|
||||
return make_float2(0.0f, 0.0f);
|
||||
const float A = 2.0f*randU.x*projA / cosI - 1.0f;
|
||||
const float A = 2.0f*randx*projA / cosI - 1.0f;
|
||||
float tmp = A*A-1.0f;
|
||||
if(fabsf(tmp) < 1e-7f)
|
||||
return make_float2(0.0f, 0.0f);
|
||||
@@ -64,24 +64,24 @@ ccl_device_forceinline float2 mf_sampleP22_11(const float cosI, const float2 ran
|
||||
const float slopeX = (A < 0.0f || slopeX2 > 1.0f/tanI)? (tanI*tmp - D) : slopeX2;
|
||||
|
||||
float U2;
|
||||
if(randU.y >= 0.5f)
|
||||
U2 = 2.0f*(randU.y - 0.5f);
|
||||
if(randy >= 0.5f)
|
||||
U2 = 2.0f*(randy - 0.5f);
|
||||
else
|
||||
U2 = 2.0f*(0.5f - randU.y);
|
||||
U2 = 2.0f*(0.5f - randy);
|
||||
const float z = (U2*(U2*(U2*0.27385f-0.73369f)+0.46341f)) / (U2*(U2*(U2*0.093073f+0.309420f)-1.0f)+0.597999f);
|
||||
const float slopeY = z * sqrtf(1.0f + slopeX*slopeX);
|
||||
|
||||
if(randU.y >= 0.5f)
|
||||
if(randy >= 0.5f)
|
||||
return make_float2(slopeX, slopeY);
|
||||
else
|
||||
return make_float2(slopeX, -slopeY);
|
||||
}
|
||||
|
||||
/* Visible normal sampling for the GGX distribution (based on page 7 of the supplemental implementation). */
|
||||
ccl_device_forceinline float3 mf_sample_vndf(const float3 wi, const float2 alpha, const float2 randU)
|
||||
ccl_device_forceinline float3 mf_sample_vndf(const float3 wi, const float2 alpha, const float randx, const float randy)
|
||||
{
|
||||
const float3 wi_11 = normalize(make_float3(alpha.x*wi.x, alpha.y*wi.y, wi.z));
|
||||
const float2 slope_11 = mf_sampleP22_11(wi_11.z, randU);
|
||||
const float2 slope_11 = mf_sampleP22_11(wi_11.z, randx, randy);
|
||||
|
||||
const float3 cossin_phi = safe_normalize(make_float3(wi_11.x, wi_11.y, 0.0f));
|
||||
const float slope_x = alpha.x*(cossin_phi.x * slope_11.x - cossin_phi.y * slope_11.y);
|
||||
@@ -91,18 +91,15 @@ ccl_device_forceinline float3 mf_sample_vndf(const float3 wi, const float2 alpha
|
||||
return normalize(make_float3(-slope_x, -slope_y, 1.0f));
|
||||
}
|
||||
|
||||
/* === Phase functions: Glossy, Diffuse and Glass === */
|
||||
/* === Phase functions: Glossy and Glass === */
|
||||
|
||||
/* Phase function for reflective materials, either without a fresnel term (for compatibility) or with the conductive fresnel term. */
|
||||
ccl_device_forceinline float3 mf_sample_phase_glossy(const float3 wi, float3 *n, float3 *k, float3 *weight, const float3 wm)
|
||||
/* Phase function for reflective materials. */
|
||||
ccl_device_forceinline float3 mf_sample_phase_glossy(const float3 wi, float3 *weight, const float3 wm)
|
||||
{
|
||||
if(n && k)
|
||||
*weight *= fresnel_conductor(dot(wi, wm), *n, *k);
|
||||
|
||||
return -wi + 2.0f * wm * dot(wi, wm);
|
||||
}
|
||||
|
||||
ccl_device_forceinline float3 mf_eval_phase_glossy(const float3 w, const float lambda, const float3 wo, const float2 alpha, float3 *n, float3 *k)
|
||||
ccl_device_forceinline float3 mf_eval_phase_glossy(const float3 w, const float lambda, const float3 wo, const float2 alpha)
|
||||
{
|
||||
if(w.z > 0.9999f)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
@@ -123,30 +120,9 @@ ccl_device_forceinline float3 mf_eval_phase_glossy(const float3 w, const float l
|
||||
else
|
||||
phase *= D_ggx_aniso(wh, alpha);
|
||||
|
||||
if(n && k) {
|
||||
/* Apply conductive fresnel term. */
|
||||
return phase * fresnel_conductor(dotW_WH, *n, *k);
|
||||
}
|
||||
|
||||
return make_float3(phase, phase, phase);
|
||||
}
|
||||
|
||||
/* Phase function for rough lambertian diffuse surfaces. */
|
||||
ccl_device_forceinline float3 mf_sample_phase_diffuse(const float3 wm, const float randu, const float randv)
|
||||
{
|
||||
float3 tm, bm;
|
||||
make_orthonormals(wm, &tm, &bm);
|
||||
|
||||
float2 disk = concentric_sample_disk(randu, randv);
|
||||
return disk.x*tm + disk.y*bm + safe_sqrtf(1.0f - disk.x*disk.x - disk.y*disk.y)*wm;
|
||||
}
|
||||
|
||||
ccl_device_forceinline float3 mf_eval_phase_diffuse(const float3 w, const float3 wm)
|
||||
{
|
||||
const float v = max(0.0f, dot(w, wm)) * M_1_PI_F;
|
||||
return make_float3(v, v, v);
|
||||
}
|
||||
|
||||
/* Phase function for dielectric transmissive materials, including both reflection and refraction according to the dielectric fresnel term. */
|
||||
ccl_device_forceinline float3 mf_sample_phase_glass(const float3 wi, const float eta, const float3 wm, const float randV, bool *outside)
|
||||
{
|
||||
@@ -269,40 +245,69 @@ ccl_device_forceinline float mf_ggx_albedo(float r)
|
||||
return saturate(albedo);
|
||||
}
|
||||
|
||||
ccl_device_inline float mf_ggx_transmission_albedo(float a, float ior)
|
||||
{
|
||||
if(ior < 1.0f) {
|
||||
ior = 1.0f/ior;
|
||||
}
|
||||
a = saturate(a);
|
||||
ior = clamp(ior, 1.0f, 3.0f);
|
||||
float I_1 = 0.0476898f*expf(-0.978352f*(ior-0.65657f)*(ior-0.65657f)) - 0.033756f*ior + 0.993261f;
|
||||
float R_1 = (((0.116991f*a - 0.270369f)*a + 0.0501366f)*a - 0.00411511f)*a + 1.00008f;
|
||||
float I_2 = (((-2.08704f*ior + 26.3298f)*ior - 127.906f)*ior + 292.958f)*ior - 287.946f + 199.803f/(ior*ior) - 101.668f/(ior*ior*ior);
|
||||
float R_2 = ((((5.3725f*a -24.9307f)*a + 22.7437f)*a - 3.40751f)*a + 0.0986325f)*a + 0.00493504f;
|
||||
|
||||
return saturate(1.0f + I_2*R_2*0.0019127f - (1.0f - I_1)*(1.0f - R_1)*9.3205f);
|
||||
}
|
||||
|
||||
ccl_device_forceinline float mf_ggx_pdf(const float3 wi, const float3 wo, const float alpha)
|
||||
{
|
||||
float D = D_ggx(normalize(wi+wo), alpha);
|
||||
float lambda = mf_lambda(wi, make_float2(alpha, alpha));
|
||||
float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
|
||||
|
||||
float multiscatter = wo.z * M_1_PI_F;
|
||||
|
||||
float albedo = mf_ggx_albedo(alpha);
|
||||
return 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f) + (1.0f - albedo) * wo.z;
|
||||
return albedo*singlescatter + (1.0f - albedo)*multiscatter;
|
||||
}
|
||||
|
||||
ccl_device_forceinline float mf_ggx_aniso_pdf(const float3 wi, const float3 wo, const float2 alpha)
|
||||
{
|
||||
return 0.25f * D_ggx_aniso(normalize(wi+wo), alpha) / ((1.0f + mf_lambda(wi, alpha)) * wi.z) + (1.0f - mf_ggx_albedo(sqrtf(alpha.x*alpha.y))) * wo.z;
|
||||
}
|
||||
float D = D_ggx_aniso(normalize(wi+wo), alpha);
|
||||
float lambda = mf_lambda(wi, alpha);
|
||||
float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
|
||||
|
||||
ccl_device_forceinline float mf_diffuse_pdf(const float3 wo)
|
||||
{
|
||||
return M_1_PI_F * wo.z;
|
||||
float multiscatter = wo.z * M_1_PI_F;
|
||||
|
||||
float albedo = mf_ggx_albedo(sqrtf(alpha.x*alpha.y));
|
||||
return albedo*singlescatter + (1.0f - albedo)*multiscatter;
|
||||
}
|
||||
|
||||
ccl_device_forceinline float mf_glass_pdf(const float3 wi, const float3 wo, const float alpha, const float eta)
|
||||
{
|
||||
float3 wh;
|
||||
float fresnel;
|
||||
if(wi.z*wo.z > 0.0f) {
|
||||
wh = normalize(wi + wo);
|
||||
fresnel = fresnel_dielectric_cos(dot(wi, wh), eta);
|
||||
}
|
||||
else {
|
||||
wh = normalize(wi + wo*eta);
|
||||
fresnel = 1.0f - fresnel_dielectric_cos(dot(wi, wh), eta);
|
||||
}
|
||||
bool reflective = (wi.z*wo.z > 0.0f);
|
||||
|
||||
float wh_len;
|
||||
float3 wh = normalize_len(wi + (reflective? wo : (wo*eta)), &wh_len);
|
||||
if(wh.z < 0.0f)
|
||||
wh = -wh;
|
||||
float3 r_wi = (wi.z < 0.0f)? -wi: wi;
|
||||
return fresnel * max(0.0f, dot(r_wi, wh)) * D_ggx(wh, alpha) / ((1.0f + mf_lambda(r_wi, make_float2(alpha, alpha))) * r_wi.z) + fabsf(wo.z);
|
||||
float lambda = mf_lambda(r_wi, make_float2(alpha, alpha));
|
||||
float D = D_ggx(wh, alpha);
|
||||
float fresnel = fresnel_dielectric_cos(dot(r_wi, wh), eta);
|
||||
|
||||
float multiscatter = fabsf(wo.z * M_1_PI_F);
|
||||
if(reflective) {
|
||||
float singlescatter = 0.25f * D / max((1.0f + lambda) * r_wi.z, 1e-7f);
|
||||
float albedo = mf_ggx_albedo(alpha);
|
||||
return fresnel * (albedo*singlescatter + (1.0f - albedo)*multiscatter);
|
||||
}
|
||||
else {
|
||||
float singlescatter = fabsf(dot(r_wi, wh)*dot(wo, wh) * D * eta*eta / max((1.0f + lambda) * r_wi.z * wh_len*wh_len, 1e-7f));
|
||||
float albedo = mf_ggx_transmission_albedo(alpha, eta);
|
||||
return (1.0f - fresnel) * (albedo*singlescatter + (1.0f - albedo)*multiscatter);
|
||||
}
|
||||
}
|
||||
|
||||
/* === Actual random walk implementations, one version of mf_eval and mf_sample per phase function. === */
|
||||
@@ -315,13 +320,6 @@ ccl_device_forceinline float mf_glass_pdf(const float3 wi, const float3 wo, cons
|
||||
#define MF_MULTI_GLASS
|
||||
#include "kernel/closure/bsdf_microfacet_multi_impl.h"
|
||||
|
||||
/* The diffuse phase function is not implemented as a node yet. */
|
||||
#if 0
|
||||
#define MF_PHASE_FUNCTION diffuse
|
||||
#define MF_MULTI_DIFFUSE
|
||||
#include "kernel/closure/bsdf_microfacet_multi_impl.h"
|
||||
#endif
|
||||
|
||||
#define MF_PHASE_FUNCTION glossy
|
||||
#define MF_MULTI_GLOSSY
|
||||
#include "kernel/closure/bsdf_microfacet_multi_impl.h"
|
||||
@@ -362,13 +360,17 @@ ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(MicrofacetBsdf *bsdf)
|
||||
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf)
|
||||
ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
|
||||
{
|
||||
if(is_zero(bsdf->T))
|
||||
bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
|
||||
|
||||
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
|
||||
float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
|
||||
bsdf->sample_weight *= F;
|
||||
|
||||
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
||||
}
|
||||
|
||||
@@ -381,12 +383,16 @@ ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf)
|
||||
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf)
|
||||
ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
|
||||
{
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
|
||||
|
||||
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
|
||||
float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
|
||||
bsdf->sample_weight *= F;
|
||||
|
||||
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
||||
}
|
||||
|
||||
@@ -428,7 +434,7 @@ ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc
|
||||
*pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
|
||||
else
|
||||
*pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
|
||||
return mf_eval_glossy(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
|
||||
return mf_eval_glossy(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state)
|
||||
@@ -442,6 +448,10 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderC
|
||||
*omega_in = 2*dot(Z, I)*Z - I;
|
||||
*pdf = 1e6f;
|
||||
*eval = make_float3(1e6f, 1e6f, 1e6f);
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
*domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
|
||||
*domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
|
||||
#endif
|
||||
return LABEL_REFLECT|LABEL_SINGULAR;
|
||||
}
|
||||
|
||||
@@ -456,7 +466,7 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderC
|
||||
float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
|
||||
float3 localO;
|
||||
|
||||
*eval = mf_sample_glossy(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
|
||||
*eval = mf_sample_glossy(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
|
||||
if(is_aniso)
|
||||
*pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
|
||||
else
|
||||
@@ -464,6 +474,7 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderC
|
||||
*eval *= *pdf;
|
||||
|
||||
*omega_in = X*localO.x + Y*localO.y + Z*localO.z;
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
*domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
|
||||
*domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
|
||||
@@ -487,7 +498,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf)
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsdf)
|
||||
ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
|
||||
{
|
||||
bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
@@ -501,6 +512,10 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsd
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID;
|
||||
|
||||
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
|
||||
float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
|
||||
bsdf->sample_weight *= F;
|
||||
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
|
||||
}
|
||||
|
||||
|
@@ -26,24 +26,16 @@
|
||||
* the balance heuristic isn't necessarily optimal anymore.
|
||||
*/
|
||||
ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
|
||||
float3 wi,
|
||||
float3 wo,
|
||||
const bool wo_outside,
|
||||
const float3 color,
|
||||
const float alpha_x,
|
||||
const float alpha_y,
|
||||
ccl_addr_space uint *lcg_state
|
||||
#ifdef MF_MULTI_GLASS
|
||||
, const float eta
|
||||
, bool use_fresnel
|
||||
, const float3 cspec0
|
||||
#elif defined(MF_MULTI_GLOSSY)
|
||||
, float3 *n, float3 *k
|
||||
, const float eta
|
||||
, bool use_fresnel
|
||||
, const float3 cspec0
|
||||
#endif
|
||||
)
|
||||
float3 wi,
|
||||
float3 wo,
|
||||
const bool wo_outside,
|
||||
const float3 color,
|
||||
const float alpha_x,
|
||||
const float alpha_y,
|
||||
ccl_addr_space uint *lcg_state,
|
||||
const float eta,
|
||||
bool use_fresnel,
|
||||
const float3 cspec0)
|
||||
{
|
||||
/* Evaluating for a shallower incoming direction produces less noise, and the properties of the BSDF guarantee reciprocity. */
|
||||
bool swapped = false;
|
||||
@@ -77,44 +69,29 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
|
||||
/* Analytically compute single scattering for lower noise. */
|
||||
float3 eval;
|
||||
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
|
||||
const float3 wh = normalize(wi+wo);
|
||||
#ifdef MF_MULTI_GLASS
|
||||
eval = mf_eval_phase_glass(-wi, lambda_r, wo, wo_outside, alpha, eta);
|
||||
if(wo_outside)
|
||||
eval *= -lambda_r / (shadowing_lambda - lambda_r);
|
||||
else
|
||||
eval *= -lambda_r * beta(-lambda_r, shadowing_lambda+1.0f);
|
||||
|
||||
float F0 = fresnel_dielectric_cos(1.0f, eta);
|
||||
if(use_fresnel) {
|
||||
throughput = interpolate_fresnel_color(wi, normalize(wi + wo), eta, F0, cspec0);
|
||||
|
||||
eval *= throughput;
|
||||
}
|
||||
#elif defined(MF_MULTI_DIFFUSE)
|
||||
/* Diffuse has no special closed form for the single scattering bounce */
|
||||
eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
#else /* MF_MULTI_GLOSSY */
|
||||
const float3 wh = normalize(wi+wo);
|
||||
const float G2 = 1.0f / (1.0f - (lambda_r + 1.0f) + shadowing_lambda);
|
||||
float val = G2 * 0.25f / wi.z;
|
||||
if(alpha.x == alpha.y)
|
||||
val *= D_ggx(wh, alpha.x);
|
||||
else
|
||||
val *= D_ggx_aniso(wh, alpha);
|
||||
if(n && k) {
|
||||
eval = fresnel_conductor(dot(wh, wi), *n, *k) * val;
|
||||
}
|
||||
else {
|
||||
eval = make_float3(val, val, val);
|
||||
}
|
||||
eval = make_float3(val, val, val);
|
||||
#endif
|
||||
|
||||
float F0 = fresnel_dielectric_cos(1.0f, eta);
|
||||
if(use_fresnel) {
|
||||
throughput = interpolate_fresnel_color(wi, wh, eta, F0, cspec0);
|
||||
|
||||
eval = throughput * val;
|
||||
eval *= throughput;
|
||||
}
|
||||
#endif
|
||||
|
||||
float3 wr = -wi;
|
||||
float hr = 1.0f;
|
||||
@@ -123,19 +100,15 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
|
||||
bool outside = true;
|
||||
|
||||
for(int order = 0; order < 10; order++) {
|
||||
/* Sample microfacet height and normal */
|
||||
if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, lcg_step_float_addrspace(lcg_state)))
|
||||
/* Sample microfacet height. */
|
||||
float height_rand = lcg_step_float_addrspace(lcg_state);
|
||||
if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand))
|
||||
break;
|
||||
float3 wm = mf_sample_vndf(-wr, alpha, make_float2(lcg_step_float_addrspace(lcg_state),
|
||||
lcg_step_float_addrspace(lcg_state)));
|
||||
/* Sample microfacet normal. */
|
||||
float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
|
||||
float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
|
||||
float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
|
||||
|
||||
#ifdef MF_MULTI_DIFFUSE
|
||||
if(order == 0) {
|
||||
/* Compute single-scattering for diffuse. */
|
||||
const float G2_G1 = -lambda_r / (shadowing_lambda - lambda_r);
|
||||
eval += throughput * G2_G1 * mf_eval_phase_diffuse(wo, wm);
|
||||
}
|
||||
#endif
|
||||
#ifdef MF_MULTI_GLASS
|
||||
if(order == 0 && use_fresnel) {
|
||||
/* Evaluate amount of scattering towards wo on this microfacet. */
|
||||
@@ -156,10 +129,8 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
|
||||
phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
|
||||
else
|
||||
phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f/eta);
|
||||
#elif defined(MF_MULTI_DIFFUSE)
|
||||
phase = mf_eval_phase_diffuse(wo, wm);
|
||||
#else /* MF_MULTI_GLOSSY */
|
||||
phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha, n, k) * throughput;
|
||||
phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha) * throughput;
|
||||
#endif
|
||||
eval += throughput * phase * mf_G1(wo_outside? wo: -wo, mf_C1((outside == wo_outside)? hr: -hr), shadowing_lambda);
|
||||
}
|
||||
@@ -168,7 +139,8 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
|
||||
#ifdef MF_MULTI_GLASS
|
||||
bool next_outside;
|
||||
float3 wi_prev = -wr;
|
||||
wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float_addrspace(lcg_state), &next_outside);
|
||||
float phase_rand = lcg_step_float_addrspace(lcg_state);
|
||||
wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, phase_rand, &next_outside);
|
||||
if(!next_outside) {
|
||||
outside = !outside;
|
||||
wr = -wr;
|
||||
@@ -181,25 +153,17 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
|
||||
else if(use_fresnel && order > 0) {
|
||||
throughput *= interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
|
||||
}
|
||||
#elif defined(MF_MULTI_DIFFUSE)
|
||||
wr = mf_sample_phase_diffuse(wm,
|
||||
lcg_step_float_addrspace(lcg_state),
|
||||
lcg_step_float_addrspace(lcg_state));
|
||||
#else /* MF_MULTI_GLOSSY */
|
||||
if(use_fresnel && order > 0) {
|
||||
throughput *= interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
|
||||
}
|
||||
wr = mf_sample_phase_glossy(-wr, n, k, &throughput, wm);
|
||||
wr = mf_sample_phase_glossy(-wr, &throughput, wm);
|
||||
#endif
|
||||
|
||||
lambda_r = mf_lambda(wr, alpha);
|
||||
|
||||
#if defined(MF_MULTI_GLOSSY) || defined(MF_MULTI_GLASS)
|
||||
if(!use_fresnel)
|
||||
throughput *= color;
|
||||
#else
|
||||
throughput *= color;
|
||||
#endif
|
||||
|
||||
C1_r = mf_C1(hr);
|
||||
G1_r = mf_G1(wr, C1_r, lambda_r);
|
||||
@@ -215,18 +179,16 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
|
||||
* escaped the surface in wo. The function returns the throughput between wi and wo.
|
||||
* Without reflection losses due to coloring or fresnel absorption in conductors, the sampling is optimal.
|
||||
*/
|
||||
ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3 *wo, const float3 color, const float alpha_x, const float alpha_y, ccl_addr_space uint *lcg_state
|
||||
#ifdef MF_MULTI_GLASS
|
||||
, const float eta
|
||||
, bool use_fresnel
|
||||
, const float3 cspec0
|
||||
#elif defined(MF_MULTI_GLOSSY)
|
||||
, float3 *n, float3 *k
|
||||
, const float eta
|
||||
, bool use_fresnel
|
||||
, const float3 cspec0
|
||||
#endif
|
||||
)
|
||||
ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(
|
||||
float3 wi,
|
||||
float3 *wo,
|
||||
const float3 color,
|
||||
const float alpha_x,
|
||||
const float alpha_y,
|
||||
ccl_addr_space uint *lcg_state,
|
||||
const float eta,
|
||||
bool use_fresnel,
|
||||
const float3 cspec0)
|
||||
{
|
||||
const float2 alpha = make_float2(alpha_x, alpha_y);
|
||||
|
||||
@@ -237,44 +199,36 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3
|
||||
float C1_r = 1.0f;
|
||||
float G1_r = 0.0f;
|
||||
bool outside = true;
|
||||
#ifdef MF_MULTI_GLASS
|
||||
|
||||
float F0 = fresnel_dielectric_cos(1.0f, eta);
|
||||
if(use_fresnel) {
|
||||
throughput = interpolate_fresnel_color(wi, normalize(wi + wr), eta, F0, cspec0);
|
||||
}
|
||||
#elif defined(MF_MULTI_GLOSSY)
|
||||
float F0 = fresnel_dielectric_cos(1.0f, eta);
|
||||
if(use_fresnel) {
|
||||
throughput = interpolate_fresnel_color(wi, normalize(wi + wr), eta, F0, cspec0);
|
||||
}
|
||||
#endif
|
||||
|
||||
int order;
|
||||
for(order = 0; order < 10; order++) {
|
||||
/* Sample microfacet height. */
|
||||
if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, lcg_step_float_addrspace(lcg_state))) {
|
||||
float height_rand = lcg_step_float_addrspace(lcg_state);
|
||||
if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand)) {
|
||||
/* The random walk has left the surface. */
|
||||
*wo = outside? wr: -wr;
|
||||
return throughput;
|
||||
}
|
||||
/* Sample microfacet normal. */
|
||||
float3 wm = mf_sample_vndf(-wr, alpha, make_float2(lcg_step_float_addrspace(lcg_state),
|
||||
lcg_step_float_addrspace(lcg_state)));
|
||||
float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
|
||||
float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
|
||||
float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
|
||||
|
||||
/* First-bounce color is already accounted for in mix weight. */
|
||||
#if defined(MF_MULTI_GLASS) || defined(MF_MULTI_GLOSSY)
|
||||
if(!use_fresnel && order > 0)
|
||||
throughput *= color;
|
||||
#else
|
||||
if(order > 0)
|
||||
throughput *= color;
|
||||
#endif
|
||||
|
||||
/* Bounce from the microfacet. */
|
||||
#ifdef MF_MULTI_GLASS
|
||||
bool next_outside;
|
||||
float3 wi_prev = -wr;
|
||||
wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float_addrspace(lcg_state), &next_outside);
|
||||
float phase_rand = lcg_step_float_addrspace(lcg_state);
|
||||
wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, phase_rand, &next_outside);
|
||||
if(!next_outside) {
|
||||
hr = -hr;
|
||||
wr = -wr;
|
||||
@@ -294,10 +248,6 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3
|
||||
throughput *= t_color;
|
||||
}
|
||||
}
|
||||
#elif defined(MF_MULTI_DIFFUSE)
|
||||
wr = mf_sample_phase_diffuse(wm,
|
||||
lcg_step_float_addrspace(lcg_state),
|
||||
lcg_step_float_addrspace(lcg_state));
|
||||
#else /* MF_MULTI_GLOSSY */
|
||||
if(use_fresnel) {
|
||||
float3 t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
|
||||
@@ -307,7 +257,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3
|
||||
else
|
||||
throughput *= t_color;
|
||||
}
|
||||
wr = mf_sample_phase_glossy(-wr, n, k, &throughput, wm);
|
||||
wr = mf_sample_phase_glossy(-wr, &throughput, wm);
|
||||
#endif
|
||||
|
||||
/* Update random walk parameters. */
|
||||
@@ -319,6 +269,5 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3
|
||||
}
|
||||
|
||||
#undef MF_MULTI_GLASS
|
||||
#undef MF_MULTI_DIFFUSE
|
||||
#undef MF_MULTI_GLOSSY
|
||||
#undef MF_PHASE_FUNCTION
|
||||
|
@@ -58,6 +58,14 @@ ccl_device int bsdf_principled_diffuse_setup(PrincipledDiffuseBsdf *bsdf)
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device bool bsdf_principled_diffuse_merge(const ShaderClosure *a, const ShaderClosure *b)
|
||||
{
|
||||
const PrincipledDiffuseBsdf *bsdf_a = (const PrincipledDiffuseBsdf*)a;
|
||||
const PrincipledDiffuseBsdf *bsdf_b = (const PrincipledDiffuseBsdf*)b;
|
||||
|
||||
return (isequal_float3(bsdf_a->N, bsdf_b->N) && bsdf_a->roughness == bsdf_b->roughness);
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_principled_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I,
|
||||
const float3 omega_in, float *pdf)
|
||||
{
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
#define ccl_get_feature(buffer, pass) buffer[(pass)*pass_stride]
|
||||
#define ccl_get_feature(buffer, pass) (buffer)[(pass)*pass_stride]
|
||||
|
||||
/* Loop over the pixels in the range [low.x, high.x) x [low.y, high.y).
|
||||
* pixel_buffer always points to the current pixel in the first pass. */
|
||||
@@ -28,11 +28,15 @@
|
||||
pixel_buffer += buffer_w - (high.x - low.x); \
|
||||
}
|
||||
|
||||
ccl_device_inline void filter_get_features(int2 pixel, ccl_global float ccl_restrict_ptr buffer, float *features, float ccl_restrict_ptr mean, int pass_stride)
|
||||
ccl_device_inline void filter_get_features(int2 pixel,
|
||||
const ccl_global float *ccl_restrict buffer,
|
||||
float *features,
|
||||
const float *ccl_restrict mean,
|
||||
int pass_stride)
|
||||
{
|
||||
features[0] = pixel.x;
|
||||
features[1] = pixel.y;
|
||||
features[2] = ccl_get_feature(buffer, 0);
|
||||
features[2] = fabsf(ccl_get_feature(buffer, 0));
|
||||
features[3] = ccl_get_feature(buffer, 1);
|
||||
features[4] = ccl_get_feature(buffer, 2);
|
||||
features[5] = ccl_get_feature(buffer, 3);
|
||||
@@ -46,11 +50,15 @@ ccl_device_inline void filter_get_features(int2 pixel, ccl_global float ccl_rest
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void filter_get_feature_scales(int2 pixel, ccl_global float ccl_restrict_ptr buffer, float *scales, float ccl_restrict_ptr mean, int pass_stride)
|
||||
ccl_device_inline void filter_get_feature_scales(int2 pixel,
|
||||
const ccl_global float *ccl_restrict buffer,
|
||||
float *scales,
|
||||
const float *ccl_restrict mean,
|
||||
int pass_stride)
|
||||
{
|
||||
scales[0] = fabsf(pixel.x - mean[0]);
|
||||
scales[1] = fabsf(pixel.y - mean[1]);
|
||||
scales[2] = fabsf(ccl_get_feature(buffer, 0) - mean[2]);
|
||||
scales[2] = fabsf(fabsf(ccl_get_feature(buffer, 0)) - mean[2]);
|
||||
scales[3] = len_squared(make_float3(ccl_get_feature(buffer, 1) - mean[3],
|
||||
ccl_get_feature(buffer, 2) - mean[4],
|
||||
ccl_get_feature(buffer, 3) - mean[5]));
|
||||
@@ -70,26 +78,15 @@ ccl_device_inline void filter_calculate_scale(float *scale)
|
||||
scale[3] = scale[4] = scale[5] = 1.0f/max(sqrtf(scale[3]), 0.01f);
|
||||
}
|
||||
|
||||
ccl_device_inline float3 filter_get_pixel_color(ccl_global float ccl_restrict_ptr buffer, int pass_stride)
|
||||
ccl_device_inline float3 filter_get_color(const ccl_global float *ccl_restrict buffer,
|
||||
int pass_stride)
|
||||
{
|
||||
return make_float3(ccl_get_feature(buffer, 0), ccl_get_feature(buffer, 1), ccl_get_feature(buffer, 2));
|
||||
}
|
||||
|
||||
ccl_device_inline float filter_get_pixel_variance(ccl_global float ccl_restrict_ptr buffer, int pass_stride)
|
||||
{
|
||||
return average(make_float3(ccl_get_feature(buffer, 0), ccl_get_feature(buffer, 1), ccl_get_feature(buffer, 2)));
|
||||
}
|
||||
|
||||
ccl_device_inline bool filter_firefly_rejection(float3 pixel_color, float pixel_variance, float3 center_color, float sqrt_center_variance)
|
||||
{
|
||||
float color_diff = average(fabs(pixel_color - center_color));
|
||||
float variance = sqrt_center_variance + sqrtf(pixel_variance) + 0.005f;
|
||||
return (color_diff > 3.0f*variance);
|
||||
return make_float3(ccl_get_feature(buffer, 8), ccl_get_feature(buffer, 9), ccl_get_feature(buffer, 10));
|
||||
}
|
||||
|
||||
ccl_device_inline void design_row_add(float *design_row,
|
||||
int rank,
|
||||
ccl_global float ccl_restrict_ptr transform,
|
||||
const ccl_global float *ccl_restrict transform,
|
||||
int stride,
|
||||
int row,
|
||||
float feature)
|
||||
@@ -101,20 +98,20 @@ ccl_device_inline void design_row_add(float *design_row,
|
||||
|
||||
/* Fill the design row. */
|
||||
ccl_device_inline void filter_get_design_row_transform(int2 p_pixel,
|
||||
ccl_global float ccl_restrict_ptr p_buffer,
|
||||
const ccl_global float *ccl_restrict p_buffer,
|
||||
int2 q_pixel,
|
||||
ccl_global float ccl_restrict_ptr q_buffer,
|
||||
const ccl_global float *ccl_restrict q_buffer,
|
||||
int pass_stride,
|
||||
int rank,
|
||||
float *design_row,
|
||||
ccl_global float ccl_restrict_ptr transform,
|
||||
const ccl_global float *ccl_restrict transform,
|
||||
int stride)
|
||||
{
|
||||
design_row[0] = 1.0f;
|
||||
math_vector_zero(design_row+1, rank);
|
||||
design_row_add(design_row, rank, transform, stride, 0, q_pixel.x - p_pixel.x);
|
||||
design_row_add(design_row, rank, transform, stride, 1, q_pixel.y - p_pixel.y);
|
||||
design_row_add(design_row, rank, transform, stride, 2, ccl_get_feature(q_buffer, 0) - ccl_get_feature(p_buffer, 0));
|
||||
design_row_add(design_row, rank, transform, stride, 2, fabsf(ccl_get_feature(q_buffer, 0)) - fabsf(ccl_get_feature(p_buffer, 0)));
|
||||
design_row_add(design_row, rank, transform, stride, 3, ccl_get_feature(q_buffer, 1) - ccl_get_feature(p_buffer, 1));
|
||||
design_row_add(design_row, rank, transform, stride, 4, ccl_get_feature(q_buffer, 2) - ccl_get_feature(p_buffer, 2));
|
||||
design_row_add(design_row, rank, transform, stride, 5, ccl_get_feature(q_buffer, 3) - ccl_get_feature(p_buffer, 3));
|
||||
|
@@ -33,11 +33,16 @@ CCL_NAMESPACE_BEGIN
|
||||
pixel_buffer += buffer_w - (pixel.x - low.x); \
|
||||
}
|
||||
|
||||
ccl_device_inline void filter_get_features_sse(__m128 x, __m128 y, __m128 active_pixels, float ccl_restrict_ptr buffer, __m128 *features, __m128 ccl_restrict_ptr mean, int pass_stride)
|
||||
ccl_device_inline void filter_get_features_sse(__m128 x, __m128 y,
|
||||
__m128 active_pixels,
|
||||
const float *ccl_restrict buffer,
|
||||
__m128 *features,
|
||||
const __m128 *ccl_restrict mean,
|
||||
int pass_stride)
|
||||
{
|
||||
features[0] = x;
|
||||
features[1] = y;
|
||||
features[2] = ccl_get_feature_sse(0);
|
||||
features[2] = _mm_fabs_ps(ccl_get_feature_sse(0));
|
||||
features[3] = ccl_get_feature_sse(1);
|
||||
features[4] = ccl_get_feature_sse(2);
|
||||
features[5] = ccl_get_feature_sse(3);
|
||||
@@ -53,12 +58,17 @@ ccl_device_inline void filter_get_features_sse(__m128 x, __m128 y, __m128 active
|
||||
features[i] = _mm_mask_ps(features[i], active_pixels);
|
||||
}
|
||||
|
||||
ccl_device_inline void filter_get_feature_scales_sse(__m128 x, __m128 y, __m128 active_pixels, float ccl_restrict_ptr buffer, __m128 *scales, __m128 ccl_restrict_ptr mean, int pass_stride)
|
||||
ccl_device_inline void filter_get_feature_scales_sse(__m128 x, __m128 y,
|
||||
__m128 active_pixels,
|
||||
const float *ccl_restrict buffer,
|
||||
__m128 *scales,
|
||||
const __m128 *ccl_restrict mean,
|
||||
int pass_stride)
|
||||
{
|
||||
scales[0] = _mm_mask_ps(_mm_fabs_ps(_mm_sub_ps(x, mean[0])), active_pixels);
|
||||
scales[1] = _mm_mask_ps(_mm_fabs_ps(_mm_sub_ps(y, mean[1])), active_pixels);
|
||||
|
||||
scales[2] = _mm_mask_ps(_mm_fabs_ps(_mm_sub_ps(ccl_get_feature_sse(0), mean[2])), active_pixels);
|
||||
scales[2] = _mm_mask_ps(_mm_fabs_ps(_mm_sub_ps(_mm_fabs_ps(ccl_get_feature_sse(0)), mean[2])), active_pixels);
|
||||
|
||||
__m128 diff, scale;
|
||||
diff = _mm_sub_ps(ccl_get_feature_sse(1), mean[3]);
|
||||
|
@@ -48,22 +48,3 @@
|
||||
#else
|
||||
# include "kernel/filter/filter_nlm_gpu.h"
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device void kernel_filter_divide_combined(int x, int y, int sample, ccl_global float *buffers, int offset, int stride, int pass_stride, int no_denoising_offset)
|
||||
{
|
||||
ccl_global float *combined_buffer = buffers + (offset + y*stride + x);
|
||||
float fac = sample / combined_buffer[3];
|
||||
combined_buffer[0] *= fac;
|
||||
combined_buffer[1] *= fac;
|
||||
combined_buffer[2] *= fac;
|
||||
combined_buffer[3] *= fac;
|
||||
if(no_denoising_offset) {
|
||||
combined_buffer[0] += combined_buffer[no_denoising_offset+0];
|
||||
combined_buffer[1] += combined_buffer[no_denoising_offset+1];
|
||||
combined_buffer[2] += combined_buffer[no_denoising_offset+2];
|
||||
}
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -16,27 +16,39 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_inline void kernel_filter_nlm_calc_difference(int dx, int dy, float ccl_restrict_ptr weightImage, float ccl_restrict_ptr varianceImage, float *differenceImage, int4 rect, int w, int channel_offset, float a, float k_2)
|
||||
ccl_device_inline void kernel_filter_nlm_calc_difference(int dx, int dy,
|
||||
const float *ccl_restrict weight_image,
|
||||
const float *ccl_restrict variance_image,
|
||||
float *difference_image,
|
||||
int4 rect,
|
||||
int w,
|
||||
int channel_offset,
|
||||
float a,
|
||||
float k_2)
|
||||
{
|
||||
for(int y = rect.y; y < rect.w; y++) {
|
||||
for(int x = rect.x; x < rect.z; x++) {
|
||||
float diff = 0.0f;
|
||||
int numChannels = channel_offset? 3 : 1;
|
||||
for(int c = 0; c < numChannels; c++) {
|
||||
float cdiff = weightImage[c*channel_offset + y*w+x] - weightImage[c*channel_offset + (y+dy)*w+(x+dx)];
|
||||
float pvar = varianceImage[c*channel_offset + y*w+x];
|
||||
float qvar = varianceImage[c*channel_offset + (y+dy)*w+(x+dx)];
|
||||
float cdiff = weight_image[c*channel_offset + y*w+x] - weight_image[c*channel_offset + (y+dy)*w+(x+dx)];
|
||||
float pvar = variance_image[c*channel_offset + y*w+x];
|
||||
float qvar = variance_image[c*channel_offset + (y+dy)*w+(x+dx)];
|
||||
diff += (cdiff*cdiff - a*(pvar + min(pvar, qvar))) / (1e-8f + k_2*(pvar+qvar));
|
||||
}
|
||||
if(numChannels > 1) {
|
||||
diff *= 1.0f/numChannels;
|
||||
}
|
||||
differenceImage[y*w+x] = diff;
|
||||
difference_image[y*w+x] = diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void kernel_filter_nlm_blur(float ccl_restrict_ptr differenceImage, float *outImage, int4 rect, int w, int f)
|
||||
ccl_device_inline void kernel_filter_nlm_blur(const float *ccl_restrict difference_image,
|
||||
float *out_image,
|
||||
int4 rect,
|
||||
int w,
|
||||
int f)
|
||||
{
|
||||
#ifdef __KERNEL_SSE3__
|
||||
int aligned_lowx = (rect.x & ~(3));
|
||||
@@ -46,30 +58,34 @@ ccl_device_inline void kernel_filter_nlm_blur(float ccl_restrict_ptr differenceI
|
||||
const int low = max(rect.y, y-f);
|
||||
const int high = min(rect.w, y+f+1);
|
||||
for(int x = rect.x; x < rect.z; x++) {
|
||||
outImage[y*w+x] = 0.0f;
|
||||
out_image[y*w+x] = 0.0f;
|
||||
}
|
||||
for(int y1 = low; y1 < high; y1++) {
|
||||
#ifdef __KERNEL_SSE3__
|
||||
for(int x = aligned_lowx; x < aligned_highx; x+=4) {
|
||||
_mm_store_ps(outImage + y*w+x, _mm_add_ps(_mm_load_ps(outImage + y*w+x), _mm_load_ps(differenceImage + y1*w+x)));
|
||||
_mm_store_ps(out_image + y*w+x, _mm_add_ps(_mm_load_ps(out_image + y*w+x), _mm_load_ps(difference_image + y1*w+x)));
|
||||
}
|
||||
#else
|
||||
for(int x = rect.x; x < rect.z; x++) {
|
||||
outImage[y*w+x] += differenceImage[y1*w+x];
|
||||
out_image[y*w+x] += difference_image[y1*w+x];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
for(int x = rect.x; x < rect.z; x++) {
|
||||
outImage[y*w+x] *= 1.0f/(high - low);
|
||||
out_image[y*w+x] *= 1.0f/(high - low);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void kernel_filter_nlm_calc_weight(float ccl_restrict_ptr differenceImage, float *outImage, int4 rect, int w, int f)
|
||||
ccl_device_inline void kernel_filter_nlm_calc_weight(const float *ccl_restrict difference_image,
|
||||
float *out_image,
|
||||
int4 rect,
|
||||
int w,
|
||||
int f)
|
||||
{
|
||||
for(int y = rect.y; y < rect.w; y++) {
|
||||
for(int x = rect.x; x < rect.z; x++) {
|
||||
outImage[y*w+x] = 0.0f;
|
||||
out_image[y*w+x] = 0.0f;
|
||||
}
|
||||
}
|
||||
for(int dx = -f; dx <= f; dx++) {
|
||||
@@ -77,7 +93,7 @@ ccl_device_inline void kernel_filter_nlm_calc_weight(float ccl_restrict_ptr diff
|
||||
int neg_dx = min(0, dx);
|
||||
for(int y = rect.y; y < rect.w; y++) {
|
||||
for(int x = rect.x-neg_dx; x < rect.z-pos_dx; x++) {
|
||||
outImage[y*w+x] += differenceImage[y*w+dx+x];
|
||||
out_image[y*w+x] += difference_image[y*w+dx+x];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,12 +101,19 @@ ccl_device_inline void kernel_filter_nlm_calc_weight(float ccl_restrict_ptr diff
|
||||
for(int x = rect.x; x < rect.z; x++) {
|
||||
const int low = max(rect.x, x-f);
|
||||
const int high = min(rect.z, x+f+1);
|
||||
outImage[y*w+x] = expf(-max(outImage[y*w+x] * (1.0f/(high - low)), 0.0f));
|
||||
out_image[y*w+x] = fast_expf(-max(out_image[y*w+x] * (1.0f/(high - low)), 0.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void kernel_filter_nlm_update_output(int dx, int dy, float ccl_restrict_ptr differenceImage, float ccl_restrict_ptr image, float *outImage, float *accumImage, int4 rect, int w, int f)
|
||||
ccl_device_inline void kernel_filter_nlm_update_output(int dx, int dy,
|
||||
const float *ccl_restrict difference_image,
|
||||
const float *ccl_restrict image,
|
||||
float *out_image,
|
||||
float *accum_image,
|
||||
int4 rect,
|
||||
int w,
|
||||
int f)
|
||||
{
|
||||
for(int y = rect.y; y < rect.w; y++) {
|
||||
for(int x = rect.x; x < rect.z; x++) {
|
||||
@@ -98,20 +121,18 @@ ccl_device_inline void kernel_filter_nlm_update_output(int dx, int dy, float ccl
|
||||
const int high = min(rect.z, x+f+1);
|
||||
float sum = 0.0f;
|
||||
for(int x1 = low; x1 < high; x1++) {
|
||||
sum += differenceImage[y*w+x1];
|
||||
sum += difference_image[y*w+x1];
|
||||
}
|
||||
float weight = sum * (1.0f/(high - low));
|
||||
accumImage[y*w+x] += weight;
|
||||
outImage[y*w+x] += weight*image[(y+dy)*w+(x+dx)];
|
||||
accum_image[y*w+x] += weight;
|
||||
out_image[y*w+x] += weight*image[(y+dy)*w+(x+dx)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void kernel_filter_nlm_construct_gramian(int dx, int dy,
|
||||
float ccl_restrict_ptr differenceImage,
|
||||
float ccl_restrict_ptr buffer,
|
||||
float *color_pass,
|
||||
float *variance_pass,
|
||||
const float *ccl_restrict difference_image,
|
||||
const float *ccl_restrict buffer,
|
||||
float *transform,
|
||||
int *rank,
|
||||
float *XtWX,
|
||||
@@ -130,7 +151,7 @@ ccl_device_inline void kernel_filter_nlm_construct_gramian(int dx, int dy,
|
||||
const int high = min(rect.z, x+f+1);
|
||||
float sum = 0.0f;
|
||||
for(int x1 = low; x1 < high; x1++) {
|
||||
sum += differenceImage[y*w+x1];
|
||||
sum += difference_image[y*w+x1];
|
||||
}
|
||||
float weight = sum * (1.0f/(high - low));
|
||||
|
||||
@@ -144,18 +165,20 @@ ccl_device_inline void kernel_filter_nlm_construct_gramian(int dx, int dy,
|
||||
dx, dy, w, h,
|
||||
pass_stride,
|
||||
buffer,
|
||||
color_pass, variance_pass,
|
||||
l_transform, l_rank,
|
||||
weight, l_XtWX, l_XtWY, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void kernel_filter_nlm_normalize(float *outImage, float ccl_restrict_ptr accumImage, int4 rect, int w)
|
||||
ccl_device_inline void kernel_filter_nlm_normalize(float *out_image,
|
||||
const float *ccl_restrict accum_image,
|
||||
int4 rect,
|
||||
int w)
|
||||
{
|
||||
for(int y = rect.y; y < rect.w; y++) {
|
||||
for(int x = rect.x; x < rect.z; x++) {
|
||||
outImage[y*w+x] /= accumImage[y*w+x];
|
||||
out_image[y*w+x] /= accum_image[y*w+x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -18,9 +18,9 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_inline void kernel_filter_nlm_calc_difference(int x, int y,
|
||||
int dx, int dy,
|
||||
ccl_global float ccl_restrict_ptr weightImage,
|
||||
ccl_global float ccl_restrict_ptr varianceImage,
|
||||
ccl_global float *differenceImage,
|
||||
const ccl_global float *ccl_restrict weight_image,
|
||||
const ccl_global float *ccl_restrict variance_image,
|
||||
ccl_global float *difference_image,
|
||||
int4 rect, int w,
|
||||
int channel_offset,
|
||||
float a, float k_2)
|
||||
@@ -28,78 +28,76 @@ ccl_device_inline void kernel_filter_nlm_calc_difference(int x, int y,
|
||||
float diff = 0.0f;
|
||||
int numChannels = channel_offset? 3 : 1;
|
||||
for(int c = 0; c < numChannels; c++) {
|
||||
float cdiff = weightImage[c*channel_offset + y*w+x] - weightImage[c*channel_offset + (y+dy)*w+(x+dx)];
|
||||
float pvar = varianceImage[c*channel_offset + y*w+x];
|
||||
float qvar = varianceImage[c*channel_offset + (y+dy)*w+(x+dx)];
|
||||
float cdiff = weight_image[c*channel_offset + y*w+x] - weight_image[c*channel_offset + (y+dy)*w+(x+dx)];
|
||||
float pvar = variance_image[c*channel_offset + y*w+x];
|
||||
float qvar = variance_image[c*channel_offset + (y+dy)*w+(x+dx)];
|
||||
diff += (cdiff*cdiff - a*(pvar + min(pvar, qvar))) / (1e-8f + k_2*(pvar+qvar));
|
||||
}
|
||||
if(numChannels > 1) {
|
||||
diff *= 1.0f/numChannels;
|
||||
}
|
||||
differenceImage[y*w+x] = diff;
|
||||
difference_image[y*w+x] = diff;
|
||||
}
|
||||
|
||||
ccl_device_inline void kernel_filter_nlm_blur(int x, int y,
|
||||
ccl_global float ccl_restrict_ptr differenceImage,
|
||||
ccl_global float *outImage,
|
||||
const ccl_global float *ccl_restrict difference_image,
|
||||
ccl_global float *out_image,
|
||||
int4 rect, int w, int f)
|
||||
{
|
||||
float sum = 0.0f;
|
||||
const int low = max(rect.y, y-f);
|
||||
const int high = min(rect.w, y+f+1);
|
||||
for(int y1 = low; y1 < high; y1++) {
|
||||
sum += differenceImage[y1*w+x];
|
||||
sum += difference_image[y1*w+x];
|
||||
}
|
||||
sum *= 1.0f/(high-low);
|
||||
outImage[y*w+x] = sum;
|
||||
out_image[y*w+x] = sum;
|
||||
}
|
||||
|
||||
ccl_device_inline void kernel_filter_nlm_calc_weight(int x, int y,
|
||||
ccl_global float ccl_restrict_ptr differenceImage,
|
||||
ccl_global float *outImage,
|
||||
const ccl_global float *ccl_restrict difference_image,
|
||||
ccl_global float *out_image,
|
||||
int4 rect, int w, int f)
|
||||
{
|
||||
float sum = 0.0f;
|
||||
const int low = max(rect.x, x-f);
|
||||
const int high = min(rect.z, x+f+1);
|
||||
for(int x1 = low; x1 < high; x1++) {
|
||||
sum += differenceImage[y*w+x1];
|
||||
sum += difference_image[y*w+x1];
|
||||
}
|
||||
sum *= 1.0f/(high-low);
|
||||
outImage[y*w+x] = expf(-max(sum, 0.0f));
|
||||
out_image[y*w+x] = fast_expf(-max(sum, 0.0f));
|
||||
}
|
||||
|
||||
ccl_device_inline void kernel_filter_nlm_update_output(int x, int y,
|
||||
int dx, int dy,
|
||||
ccl_global float ccl_restrict_ptr differenceImage,
|
||||
ccl_global float ccl_restrict_ptr image,
|
||||
ccl_global float *outImage,
|
||||
ccl_global float *accumImage,
|
||||
const ccl_global float *ccl_restrict difference_image,
|
||||
const ccl_global float *ccl_restrict image,
|
||||
ccl_global float *out_image,
|
||||
ccl_global float *accum_image,
|
||||
int4 rect, int w, int f)
|
||||
{
|
||||
float sum = 0.0f;
|
||||
const int low = max(rect.x, x-f);
|
||||
const int high = min(rect.z, x+f+1);
|
||||
for(int x1 = low; x1 < high; x1++) {
|
||||
sum += differenceImage[y*w+x1];
|
||||
sum += difference_image[y*w+x1];
|
||||
}
|
||||
sum *= 1.0f/(high-low);
|
||||
if(outImage) {
|
||||
accumImage[y*w+x] += sum;
|
||||
outImage[y*w+x] += sum*image[(y+dy)*w+(x+dx)];
|
||||
if(out_image) {
|
||||
accum_image[y*w+x] += sum;
|
||||
out_image[y*w+x] += sum*image[(y+dy)*w+(x+dx)];
|
||||
}
|
||||
else {
|
||||
accumImage[y*w+x] = sum;
|
||||
accum_image[y*w+x] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void kernel_filter_nlm_construct_gramian(int fx, int fy,
|
||||
int dx, int dy,
|
||||
ccl_global float ccl_restrict_ptr differenceImage,
|
||||
ccl_global float ccl_restrict_ptr buffer,
|
||||
ccl_global float *color_pass,
|
||||
ccl_global float *variance_pass,
|
||||
ccl_global float ccl_restrict_ptr transform,
|
||||
const ccl_global float *ccl_restrict difference_image,
|
||||
const ccl_global float *ccl_restrict buffer,
|
||||
const ccl_global float *ccl_restrict transform,
|
||||
ccl_global int *rank,
|
||||
ccl_global float *XtWX,
|
||||
ccl_global float3 *XtWY,
|
||||
@@ -115,7 +113,7 @@ ccl_device_inline void kernel_filter_nlm_construct_gramian(int fx, int fy,
|
||||
const int high = min(rect.z, x+f+1);
|
||||
float sum = 0.0f;
|
||||
for(int x1 = low; x1 < high; x1++) {
|
||||
sum += differenceImage[y*w+x1];
|
||||
sum += difference_image[y*w+x1];
|
||||
}
|
||||
float weight = sum * (1.0f/(high - low));
|
||||
|
||||
@@ -130,18 +128,17 @@ ccl_device_inline void kernel_filter_nlm_construct_gramian(int fx, int fy,
|
||||
dx, dy, w, h,
|
||||
pass_stride,
|
||||
buffer,
|
||||
color_pass, variance_pass,
|
||||
transform, rank,
|
||||
weight, XtWX, XtWY,
|
||||
localIdx);
|
||||
}
|
||||
|
||||
ccl_device_inline void kernel_filter_nlm_normalize(int x, int y,
|
||||
ccl_global float *outImage,
|
||||
ccl_global float ccl_restrict_ptr accumImage,
|
||||
ccl_global float *out_image,
|
||||
const ccl_global float *ccl_restrict accum_image,
|
||||
int4 rect, int w)
|
||||
{
|
||||
outImage[y*w+x] /= accumImage[y*w+x];
|
||||
out_image[y*w+x] /= accum_image[y*w+x];
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -44,7 +44,7 @@ ccl_device void kernel_filter_divide_shadow(int sample,
|
||||
|
||||
int offset = tiles->offsets[tile];
|
||||
int stride = tiles->strides[tile];
|
||||
ccl_global float ccl_restrict_ptr center_buffer = (ccl_global float*) tiles->buffers[tile];
|
||||
const ccl_global float *ccl_restrict center_buffer = (ccl_global float*) tiles->buffers[tile];
|
||||
center_buffer += (y*stride + x + offset)*buffer_pass_stride;
|
||||
center_buffer += buffer_denoising_offset + 14;
|
||||
|
||||
@@ -61,8 +61,8 @@ ccl_device void kernel_filter_divide_shadow(int sample,
|
||||
varA = max(0.0f, varA - unfilteredA[idx]*unfilteredA[idx]*odd_sample);
|
||||
varB = max(0.0f, varB - unfilteredB[idx]*unfilteredB[idx]*even_sample);
|
||||
}
|
||||
varA /= (odd_sample - 1);
|
||||
varB /= (even_sample - 1);
|
||||
varA /= max(odd_sample - 1, 1);
|
||||
varB /= max(even_sample - 1, 1);
|
||||
|
||||
sampleVariance[idx] = 0.5f*(varA + varB) / sample;
|
||||
sampleVarianceV[idx] = 0.5f * (varA - varB) * (varA - varB) / (sample*sample);
|
||||
@@ -77,7 +77,7 @@ ccl_device void kernel_filter_divide_shadow(int sample,
|
||||
* - mean, variance: Target denoise buffers.
|
||||
* - rect: The prefilter area (lower pixels inclusive, upper pixels exclusive).
|
||||
*/
|
||||
ccl_device void kernel_filter_get_feature(int sample,
|
||||
ccl_device void kernel_filter_get_feature(int sample,
|
||||
ccl_global TilesInfo *tiles,
|
||||
int m_offset, int v_offset,
|
||||
int x, int y,
|
||||
@@ -96,14 +96,87 @@ ccl_device void kernel_filter_get_feature(int sample,
|
||||
int idx = (y-rect.y)*buffer_w + (x - rect.x);
|
||||
|
||||
mean[idx] = center_buffer[m_offset] / sample;
|
||||
if(use_split_variance) {
|
||||
variance[idx] = max(0.0f, (center_buffer[v_offset] - mean[idx]*mean[idx]*sample) / (sample * (sample-1)));
|
||||
if (sample > 1) {
|
||||
if(use_split_variance) {
|
||||
variance[idx] = max(0.0f, (center_buffer[v_offset] - mean[idx]*mean[idx]*sample) / (sample * (sample-1)));
|
||||
}
|
||||
else {
|
||||
variance[idx] = center_buffer[v_offset] / (sample * (sample-1));
|
||||
}
|
||||
}
|
||||
else {
|
||||
variance[idx] = center_buffer[v_offset] / (sample * (sample-1));
|
||||
/* Can't compute variance with single sample, just set it very high. */
|
||||
variance[idx] = 1e10f;
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device void kernel_filter_detect_outliers(int x, int y,
|
||||
ccl_global float *image,
|
||||
ccl_global float *variance,
|
||||
ccl_global float *depth,
|
||||
ccl_global float *out,
|
||||
int4 rect,
|
||||
int pass_stride)
|
||||
{
|
||||
int buffer_w = align_up(rect.z - rect.x, 4);
|
||||
|
||||
int idx = (y-rect.y)*buffer_w + (x-rect.x);
|
||||
float3 color = make_float3(image[idx], image[idx+pass_stride], image[idx+2*pass_stride]);
|
||||
|
||||
float fac = 1.0f;
|
||||
if(color.x < 0.0f || color.y < 0.0f || color.z < 0.0f) {
|
||||
depth[idx] = -depth[idx];
|
||||
fac = 0.0f;
|
||||
}
|
||||
else {
|
||||
float L = average(color);
|
||||
int n = 0;
|
||||
float values[25];
|
||||
for(int y1 = max(y-2, rect.y); y1 < min(y+3, rect.w); y1++) {
|
||||
for(int x1 = max(x-2, rect.x); x1 < min(x+3, rect.z); x1++) {
|
||||
int idx = (y1-rect.y)*buffer_w + (x1-rect.x);
|
||||
float L = average(make_float3(image[idx], image[idx+pass_stride], image[idx+2*pass_stride]));
|
||||
|
||||
/* Find the position of L. */
|
||||
int i;
|
||||
for(i = 0; i < n; i++) {
|
||||
if(values[i] > L) break;
|
||||
}
|
||||
/* Make space for L by shifting all following values to the right. */
|
||||
for(int j = n; j > i; j--) {
|
||||
values[j] = values[j-1];
|
||||
}
|
||||
/* Insert L. */
|
||||
values[i] = L;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
float ref = 2.0f*values[(int)(n*0.75f)];
|
||||
if(L > ref) {
|
||||
/* The pixel appears to be an outlier.
|
||||
* However, it may just be a legitimate highlight. Therefore, it is checked how likely it is that the pixel
|
||||
* should actually be at the reference value:
|
||||
* If the reference is within the 3-sigma interval, the pixel is assumed to be a statistical outlier.
|
||||
* Otherwise, it is very unlikely that the pixel should be darker, which indicates a legitimate highlight.
|
||||
*/
|
||||
float stddev = sqrtf(average(make_float3(variance[idx], variance[idx+pass_stride], variance[idx+2*pass_stride])));
|
||||
if(L - 3*stddev < ref) {
|
||||
/* The pixel is an outlier, so negate the depth value to mark it as one.
|
||||
* Also, scale its brightness down to the outlier threshold to avoid trouble with the NLM weights. */
|
||||
depth[idx] = -depth[idx];
|
||||
fac = ref/L;
|
||||
variance[idx ] *= fac*fac;
|
||||
variance[idx + pass_stride] *= fac*fac;
|
||||
variance[idx+2*pass_stride] *= fac*fac;
|
||||
}
|
||||
}
|
||||
}
|
||||
out[idx ] = fac*image[idx];
|
||||
out[idx + pass_stride] = fac*image[idx + pass_stride];
|
||||
out[idx+2*pass_stride] = fac*image[idx+2*pass_stride];
|
||||
}
|
||||
|
||||
/* Combine A/B buffers.
|
||||
* Calculates the combined mean and the buffer variance. */
|
||||
ccl_device void kernel_filter_combine_halves(int x, int y,
|
||||
|
@@ -21,40 +21,39 @@ ccl_device_inline void kernel_filter_construct_gramian(int x, int y,
|
||||
int dx, int dy,
|
||||
int w, int h,
|
||||
int pass_stride,
|
||||
ccl_global float ccl_restrict_ptr buffer,
|
||||
ccl_global float *color_pass,
|
||||
ccl_global float *variance_pass,
|
||||
ccl_global float ccl_restrict_ptr transform,
|
||||
const ccl_global float *ccl_restrict buffer,
|
||||
const ccl_global float *ccl_restrict transform,
|
||||
ccl_global int *rank,
|
||||
float weight,
|
||||
ccl_global float *XtWX,
|
||||
ccl_global float3 *XtWY,
|
||||
int localIdx)
|
||||
{
|
||||
if(weight < 1e-3f) {
|
||||
return;
|
||||
}
|
||||
|
||||
int p_offset = y *w + x;
|
||||
int q_offset = (y+dy)*w + (x+dx);
|
||||
|
||||
#ifdef __KERNEL_CPU__
|
||||
const int stride = 1;
|
||||
(void)storage_stride;
|
||||
(void)localIdx;
|
||||
float design_row[DENOISE_FEATURES+1];
|
||||
#elif defined(__KERNEL_CUDA__)
|
||||
#ifdef __KERNEL_GPU__
|
||||
const int stride = storage_stride;
|
||||
#else
|
||||
const int stride = 1;
|
||||
(void) storage_stride;
|
||||
#endif
|
||||
|
||||
#ifdef __KERNEL_CUDA__
|
||||
ccl_local float shared_design_row[(DENOISE_FEATURES+1)*CCL_MAX_LOCAL_SIZE];
|
||||
ccl_local_param float *design_row = shared_design_row + localIdx*(DENOISE_FEATURES+1);
|
||||
#else
|
||||
const int stride = storage_stride;
|
||||
float design_row[DENOISE_FEATURES+1];
|
||||
#endif
|
||||
|
||||
float3 p_color = filter_get_pixel_color(color_pass + p_offset, pass_stride);
|
||||
float3 q_color = filter_get_pixel_color(color_pass + q_offset, pass_stride);
|
||||
float3 q_color = filter_get_color(buffer + q_offset, pass_stride);
|
||||
|
||||
float p_std_dev = sqrtf(filter_get_pixel_variance(variance_pass + p_offset, pass_stride));
|
||||
float q_std_dev = sqrtf(filter_get_pixel_variance(variance_pass + q_offset, pass_stride));
|
||||
|
||||
if(average(fabs(p_color - q_color)) > 3.0f*(p_std_dev + q_std_dev + 1e-3f)) {
|
||||
/* If the pixel was flagged as an outlier during prefiltering, skip it. */
|
||||
if(ccl_get_feature(buffer + q_offset, 0) < 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -75,16 +74,33 @@ ccl_device_inline void kernel_filter_finalize(int x, int y, int w, int h,
|
||||
int4 buffer_params,
|
||||
int sample)
|
||||
{
|
||||
#ifdef __KERNEL_CPU__
|
||||
const int stride = 1;
|
||||
(void)storage_stride;
|
||||
#else
|
||||
#ifdef __KERNEL_GPU__
|
||||
const int stride = storage_stride;
|
||||
#else
|
||||
const int stride = 1;
|
||||
(void) storage_stride;
|
||||
#endif
|
||||
|
||||
if(XtWX[0] < 1e-3f) {
|
||||
/* There is not enough information to determine a denoised result.
|
||||
* As a fallback, keep the original value of the pixel. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* The weighted average of pixel colors (essentially, the NLM-filtered image).
|
||||
* In case the solution of the linear model fails due to numerical issues,
|
||||
* fall back to this value. */
|
||||
float3 mean_color = XtWY[0]/XtWX[0];
|
||||
|
||||
math_trimatrix_vec3_solve(XtWX, XtWY, (*rank)+1, stride);
|
||||
|
||||
float3 final_color = XtWY[0];
|
||||
if(!isfinite3_safe(final_color)) {
|
||||
final_color = mean_color;
|
||||
}
|
||||
|
||||
/* Clamp pixel value to positive values. */
|
||||
final_color = max(final_color, make_float3(0.0f, 0.0f, 0.0f));
|
||||
|
||||
ccl_global float *combined_buffer = buffer + (y*buffer_params.y + x + buffer_params.x)*buffer_params.z;
|
||||
final_color *= sample;
|
||||
@@ -98,6 +114,4 @@ ccl_device_inline void kernel_filter_finalize(int x, int y, int w, int h,
|
||||
combined_buffer[2] = final_color.z;
|
||||
}
|
||||
|
||||
#undef STORAGE_TYPE
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device void kernel_filter_construct_transform(float ccl_restrict_ptr buffer,
|
||||
ccl_device void kernel_filter_construct_transform(const float *ccl_restrict buffer,
|
||||
int x, int y, int4 rect,
|
||||
int pass_stride,
|
||||
float *transform, int *rank,
|
||||
@@ -29,20 +29,15 @@ ccl_device void kernel_filter_construct_transform(float ccl_restrict_ptr buffer,
|
||||
/* Temporary storage, used in different steps of the algorithm. */
|
||||
float tempmatrix[DENOISE_FEATURES*DENOISE_FEATURES];
|
||||
float tempvector[2*DENOISE_FEATURES];
|
||||
float ccl_restrict_ptr pixel_buffer;
|
||||
const float *ccl_restrict pixel_buffer;
|
||||
int2 pixel;
|
||||
|
||||
|
||||
|
||||
|
||||
/* === Calculate denoising window. === */
|
||||
int2 low = make_int2(max(rect.x, x - radius),
|
||||
max(rect.y, y - radius));
|
||||
int2 high = make_int2(min(rect.z, x + radius + 1),
|
||||
min(rect.w, y + radius + 1));
|
||||
|
||||
|
||||
|
||||
int num_pixels = (high.y - low.y) * (high.x - low.x);
|
||||
|
||||
/* === Shift feature passes to have mean 0. === */
|
||||
float feature_means[DENOISE_FEATURES];
|
||||
@@ -52,8 +47,7 @@ ccl_device void kernel_filter_construct_transform(float ccl_restrict_ptr buffer,
|
||||
math_vector_add(feature_means, features, DENOISE_FEATURES);
|
||||
} END_FOR_PIXEL_WINDOW
|
||||
|
||||
float pixel_scale = 1.0f / ((high.y - low.y) * (high.x - low.x));
|
||||
math_vector_scale(feature_means, pixel_scale, DENOISE_FEATURES);
|
||||
math_vector_scale(feature_means, 1.0f / num_pixels, DENOISE_FEATURES);
|
||||
|
||||
/* === Scale the shifted feature passes to a range of [-1; 1], will be baked into the transform later. === */
|
||||
float *feature_scale = tempvector;
|
||||
@@ -66,7 +60,6 @@ ccl_device void kernel_filter_construct_transform(float ccl_restrict_ptr buffer,
|
||||
|
||||
filter_calculate_scale(feature_scale);
|
||||
|
||||
|
||||
/* === Generate the feature transformation. ===
|
||||
* This transformation maps the DENOISE_FEATURES-dimentional feature space to a reduced feature (r-feature) space
|
||||
* which generally has fewer dimensions. This mainly helps to prevent overfitting. */
|
||||
@@ -80,6 +73,8 @@ ccl_device void kernel_filter_construct_transform(float ccl_restrict_ptr buffer,
|
||||
|
||||
math_matrix_jacobi_eigendecomposition(feature_matrix, transform, DENOISE_FEATURES, 1);
|
||||
*rank = 0;
|
||||
/* Prevent overfitting when a small window is used. */
|
||||
int max_rank = min(DENOISE_FEATURES, num_pixels/3);
|
||||
if(pca_threshold < 0.0f) {
|
||||
float threshold_energy = 0.0f;
|
||||
for(int i = 0; i < DENOISE_FEATURES; i++) {
|
||||
@@ -88,24 +83,25 @@ ccl_device void kernel_filter_construct_transform(float ccl_restrict_ptr buffer,
|
||||
threshold_energy *= 1.0f - (-pca_threshold);
|
||||
|
||||
float reduced_energy = 0.0f;
|
||||
for(int i = 0; i < DENOISE_FEATURES; i++, (*rank)++) {
|
||||
for(int i = 0; i < max_rank; i++, (*rank)++) {
|
||||
if(i >= 2 && reduced_energy >= threshold_energy)
|
||||
break;
|
||||
float s = feature_matrix[i*DENOISE_FEATURES+i];
|
||||
reduced_energy += s;
|
||||
/* Bake the feature scaling into the transformation matrix. */
|
||||
math_vector_mul(transform + (*rank)*DENOISE_FEATURES, feature_scale, DENOISE_FEATURES);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(int i = 0; i < DENOISE_FEATURES; i++, (*rank)++) {
|
||||
for(int i = 0; i < max_rank; i++, (*rank)++) {
|
||||
float s = feature_matrix[i*DENOISE_FEATURES+i];
|
||||
if(i >= 2 && sqrtf(s) < pca_threshold)
|
||||
break;
|
||||
/* Bake the feature scaling into the transformation matrix. */
|
||||
math_vector_mul(transform + (*rank)*DENOISE_FEATURES, feature_scale, DENOISE_FEATURES);
|
||||
}
|
||||
}
|
||||
|
||||
/* Bake the feature scaling into the transformation matrix. */
|
||||
for(int i = 0; i < (*rank); i++) {
|
||||
math_vector_mul(transform + i*DENOISE_FEATURES, feature_scale, DENOISE_FEATURES);
|
||||
}
|
||||
math_matrix_transpose(transform, DENOISE_FEATURES, 1);
|
||||
}
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device void kernel_filter_construct_transform(ccl_global float ccl_restrict_ptr buffer,
|
||||
ccl_device void kernel_filter_construct_transform(const ccl_global float *ccl_restrict buffer,
|
||||
int x, int y, int4 rect,
|
||||
int pass_stride,
|
||||
ccl_global float *transform,
|
||||
@@ -38,7 +38,8 @@ ccl_device void kernel_filter_construct_transform(ccl_global float ccl_restrict_
|
||||
max(rect.y, y - radius));
|
||||
int2 high = make_int2(min(rect.z, x + radius + 1),
|
||||
min(rect.w, y + radius + 1));
|
||||
ccl_global float ccl_restrict_ptr pixel_buffer;
|
||||
int num_pixels = (high.y - low.y) * (high.x - low.x);
|
||||
const ccl_global float *ccl_restrict pixel_buffer;
|
||||
int2 pixel;
|
||||
|
||||
|
||||
@@ -52,8 +53,7 @@ ccl_device void kernel_filter_construct_transform(ccl_global float ccl_restrict_
|
||||
math_vector_add(feature_means, features, DENOISE_FEATURES);
|
||||
} END_FOR_PIXEL_WINDOW
|
||||
|
||||
float pixel_scale = 1.0f / ((high.y - low.y) * (high.x - low.x));
|
||||
math_vector_scale(feature_means, pixel_scale, DENOISE_FEATURES);
|
||||
math_vector_scale(feature_means, 1.0f / num_pixels, DENOISE_FEATURES);
|
||||
|
||||
/* === Scale the shifted feature passes to a range of [-1; 1], will be baked into the transform later. === */
|
||||
float feature_scale[DENOISE_FEATURES];
|
||||
@@ -81,6 +81,8 @@ ccl_device void kernel_filter_construct_transform(ccl_global float ccl_restrict_
|
||||
|
||||
math_matrix_jacobi_eigendecomposition(feature_matrix, transform, DENOISE_FEATURES, transform_stride);
|
||||
*rank = 0;
|
||||
/* Prevent overfitting when a small window is used. */
|
||||
int max_rank = min(DENOISE_FEATURES, num_pixels/3);
|
||||
if(pca_threshold < 0.0f) {
|
||||
float threshold_energy = 0.0f;
|
||||
for(int i = 0; i < DENOISE_FEATURES; i++) {
|
||||
@@ -89,25 +91,29 @@ ccl_device void kernel_filter_construct_transform(ccl_global float ccl_restrict_
|
||||
threshold_energy *= 1.0f - (-pca_threshold);
|
||||
|
||||
float reduced_energy = 0.0f;
|
||||
for(int i = 0; i < DENOISE_FEATURES; i++, (*rank)++) {
|
||||
for(int i = 0; i < max_rank; i++, (*rank)++) {
|
||||
if(i >= 2 && reduced_energy >= threshold_energy)
|
||||
break;
|
||||
float s = feature_matrix[i*DENOISE_FEATURES+i];
|
||||
reduced_energy += s;
|
||||
/* Bake the feature scaling into the transformation matrix. */
|
||||
math_vector_mul_strided(transform + i*DENOISE_FEATURES*transform_stride, feature_scale, transform_stride, DENOISE_FEATURES);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(int i = 0; i < DENOISE_FEATURES; i++, (*rank)++) {
|
||||
for(int i = 0; i < max_rank; i++, (*rank)++) {
|
||||
float s = feature_matrix[i*DENOISE_FEATURES+i];
|
||||
if(i >= 2 && sqrtf(s) < pca_threshold)
|
||||
break;
|
||||
/* Bake the feature scaling into the transformation matrix. */
|
||||
math_vector_mul_strided(transform + i*DENOISE_FEATURES*transform_stride, feature_scale, transform_stride, DENOISE_FEATURES);
|
||||
}
|
||||
}
|
||||
|
||||
math_matrix_transpose(transform, DENOISE_FEATURES, transform_stride);
|
||||
|
||||
/* Bake the feature scaling into the transformation matrix. */
|
||||
for(int i = 0; i < DENOISE_FEATURES; i++) {
|
||||
for(int j = 0; j < (*rank); j++) {
|
||||
transform[(i*DENOISE_FEATURES + j)*transform_stride] *= feature_scale[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device void kernel_filter_construct_transform(float ccl_restrict_ptr buffer,
|
||||
ccl_device void kernel_filter_construct_transform(const float *ccl_restrict buffer,
|
||||
int x, int y, int4 rect,
|
||||
int pass_stride,
|
||||
float *transform, int *rank,
|
||||
@@ -25,13 +25,14 @@ ccl_device void kernel_filter_construct_transform(float ccl_restrict_ptr buffer,
|
||||
int buffer_w = align_up(rect.z - rect.x, 4);
|
||||
|
||||
__m128 features[DENOISE_FEATURES];
|
||||
float ccl_restrict_ptr pixel_buffer;
|
||||
const float *ccl_restrict pixel_buffer;
|
||||
int2 pixel;
|
||||
|
||||
int2 low = make_int2(max(rect.x, x - radius),
|
||||
max(rect.y, y - radius));
|
||||
int2 high = make_int2(min(rect.z, x + radius + 1),
|
||||
min(rect.w, y + radius + 1));
|
||||
int num_pixels = (high.y - low.y) * (high.x - low.x);
|
||||
|
||||
__m128 feature_means[DENOISE_FEATURES];
|
||||
math_vector_zero_sse(feature_means, DENOISE_FEATURES);
|
||||
@@ -40,7 +41,7 @@ ccl_device void kernel_filter_construct_transform(float ccl_restrict_ptr buffer,
|
||||
math_vector_add_sse(feature_means, DENOISE_FEATURES, features);
|
||||
} END_FOR_PIXEL_WINDOW_SSE
|
||||
|
||||
__m128 pixel_scale = _mm_set1_ps(1.0f / ((high.y - low.y) * (high.x - low.x)));
|
||||
__m128 pixel_scale = _mm_set1_ps(1.0f / num_pixels);
|
||||
for(int i = 0; i < DENOISE_FEATURES; i++) {
|
||||
feature_means[i] = _mm_mul_ps(_mm_hsum_ps(feature_means[i]), pixel_scale);
|
||||
}
|
||||
@@ -49,8 +50,7 @@ ccl_device void kernel_filter_construct_transform(float ccl_restrict_ptr buffer,
|
||||
math_vector_zero_sse(feature_scale, DENOISE_FEATURES);
|
||||
FOR_PIXEL_WINDOW_SSE {
|
||||
filter_get_feature_scales_sse(x4, y4, active_pixels, pixel_buffer, features, feature_means, pass_stride);
|
||||
for(int i = 0; i < DENOISE_FEATURES; i++)
|
||||
feature_scale[i] = _mm_max_ps(feature_scale[i], features[i]);
|
||||
math_vector_max_sse(feature_scale, features, DENOISE_FEATURES);
|
||||
} END_FOR_PIXEL_WINDOW_SSE
|
||||
|
||||
filter_calculate_scale_sse(feature_scale);
|
||||
@@ -69,6 +69,8 @@ ccl_device void kernel_filter_construct_transform(float ccl_restrict_ptr buffer,
|
||||
math_matrix_jacobi_eigendecomposition(feature_matrix, transform, DENOISE_FEATURES, 1);
|
||||
|
||||
*rank = 0;
|
||||
/* Prevent overfitting when a small window is used. */
|
||||
int max_rank = min(DENOISE_FEATURES, num_pixels/3);
|
||||
if(pca_threshold < 0.0f) {
|
||||
float threshold_energy = 0.0f;
|
||||
for(int i = 0; i < DENOISE_FEATURES; i++) {
|
||||
@@ -77,29 +79,27 @@ ccl_device void kernel_filter_construct_transform(float ccl_restrict_ptr buffer,
|
||||
threshold_energy *= 1.0f - (-pca_threshold);
|
||||
|
||||
float reduced_energy = 0.0f;
|
||||
for(int i = 0; i < DENOISE_FEATURES; i++, (*rank)++) {
|
||||
for(int i = 0; i < max_rank; i++, (*rank)++) {
|
||||
if(i >= 2 && reduced_energy >= threshold_energy)
|
||||
break;
|
||||
float s = feature_matrix[i*DENOISE_FEATURES+i];
|
||||
reduced_energy += s;
|
||||
/* Bake the feature scaling into the transformation matrix. */
|
||||
for(int j = 0; j < DENOISE_FEATURES; j++) {
|
||||
transform[(*rank)*DENOISE_FEATURES + j] *= _mm_cvtss_f32(feature_scale[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(int i = 0; i < DENOISE_FEATURES; i++, (*rank)++) {
|
||||
for(int i = 0; i < max_rank; i++, (*rank)++) {
|
||||
float s = feature_matrix[i*DENOISE_FEATURES+i];
|
||||
if(i >= 2 && sqrtf(s) < pca_threshold)
|
||||
break;
|
||||
/* Bake the feature scaling into the transformation matrix. */
|
||||
for(int j = 0; j < DENOISE_FEATURES; j++) {
|
||||
transform[(*rank)*DENOISE_FEATURES + j] *= _mm_cvtss_f32(feature_scale[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
math_matrix_transpose(transform, DENOISE_FEATURES, 1);
|
||||
|
||||
/* Bake the feature scaling into the transformation matrix. */
|
||||
for(int i = 0; i < DENOISE_FEATURES; i++) {
|
||||
math_vector_scale(transform + i*DENOISE_FEATURES, _mm_cvtss_f32(feature_scale[i]), *rank);
|
||||
}
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -220,7 +220,9 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
|
||||
#ifdef __SHADOW_TRICKS__
|
||||
L->path_total = make_float3(0.0f, 0.0f, 0.0f);
|
||||
L->path_total_shaded = make_float3(0.0f, 0.0f, 0.0f);
|
||||
L->shadow_color = make_float3(0.0f, 0.0f, 0.0f);
|
||||
L->shadow_background_color = make_float3(0.0f, 0.0f, 0.0f);
|
||||
L->shadow_radiance_sum = make_float3(0.0f, 0.0f, 0.0f);
|
||||
L->shadow_throughput = 0.0f;
|
||||
#endif
|
||||
|
||||
#ifdef __DENOISING_FEATURES__
|
||||
@@ -621,25 +623,43 @@ ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance
|
||||
{
|
||||
float fac = 1.0f/num_samples;
|
||||
|
||||
#ifdef __SPLIT_KERNEL__
|
||||
# define safe_float3_add(f, v) \
|
||||
do { \
|
||||
ccl_global float *p = (ccl_global float*)(&(f)); \
|
||||
atomic_add_and_fetch_float(p+0, (v).x); \
|
||||
atomic_add_and_fetch_float(p+1, (v).y); \
|
||||
atomic_add_and_fetch_float(p+2, (v).z); \
|
||||
} while(0)
|
||||
#else
|
||||
# define safe_float3_add(f, v) (f) += (v)
|
||||
#endif /* __SPLIT_KERNEL__ */
|
||||
|
||||
#ifdef __PASSES__
|
||||
L->direct_diffuse += L_sample->direct_diffuse*fac;
|
||||
L->direct_glossy += L_sample->direct_glossy*fac;
|
||||
L->direct_transmission += L_sample->direct_transmission*fac;
|
||||
L->direct_subsurface += L_sample->direct_subsurface*fac;
|
||||
L->direct_scatter += L_sample->direct_scatter*fac;
|
||||
safe_float3_add(L->direct_diffuse, L_sample->direct_diffuse*fac);
|
||||
safe_float3_add(L->direct_glossy, L_sample->direct_glossy*fac);
|
||||
safe_float3_add(L->direct_transmission, L_sample->direct_transmission*fac);
|
||||
safe_float3_add(L->direct_subsurface, L_sample->direct_subsurface*fac);
|
||||
safe_float3_add(L->direct_scatter, L_sample->direct_scatter*fac);
|
||||
|
||||
L->indirect_diffuse += L_sample->indirect_diffuse*fac;
|
||||
L->indirect_glossy += L_sample->indirect_glossy*fac;
|
||||
L->indirect_transmission += L_sample->indirect_transmission*fac;
|
||||
L->indirect_subsurface += L_sample->indirect_subsurface*fac;
|
||||
L->indirect_scatter += L_sample->indirect_scatter*fac;
|
||||
safe_float3_add(L->indirect_diffuse, L_sample->indirect_diffuse*fac);
|
||||
safe_float3_add(L->indirect_glossy, L_sample->indirect_glossy*fac);
|
||||
safe_float3_add(L->indirect_transmission, L_sample->indirect_transmission*fac);
|
||||
safe_float3_add(L->indirect_subsurface, L_sample->indirect_subsurface*fac);
|
||||
safe_float3_add(L->indirect_scatter, L_sample->indirect_scatter*fac);
|
||||
|
||||
L->background += L_sample->background*fac;
|
||||
L->ao += L_sample->ao*fac;
|
||||
L->shadow += L_sample->shadow*fac;
|
||||
safe_float3_add(L->background, L_sample->background*fac);
|
||||
safe_float3_add(L->ao, L_sample->ao*fac);
|
||||
safe_float3_add(L->shadow, L_sample->shadow*fac);
|
||||
# ifdef __SPLIT_KERNEL__
|
||||
atomic_add_and_fetch_float(&L->mist, L_sample->mist*fac);
|
||||
# else
|
||||
L->mist += L_sample->mist*fac;
|
||||
#endif
|
||||
L->emission += L_sample->emission * fac;
|
||||
# endif /* __SPLIT_KERNEL__ */
|
||||
#endif /* __PASSES__ */
|
||||
safe_float3_add(L->emission, L_sample->emission*fac);
|
||||
|
||||
#undef safe_float3_add
|
||||
}
|
||||
|
||||
#ifdef __SHADOW_TRICKS__
|
||||
@@ -662,11 +682,12 @@ ccl_device_inline float3 path_radiance_sum_shadowcatcher(KernelGlobals *kg,
|
||||
const float shadow = path_radiance_sum_shadow(L);
|
||||
float3 L_sum;
|
||||
if(kernel_data.background.transparent) {
|
||||
*alpha = 1.0f-shadow;
|
||||
L_sum = make_float3(0.0f, 0.0f, 0.0f);
|
||||
*alpha = 1.0f - L->shadow_throughput * shadow;
|
||||
L_sum = L->shadow_radiance_sum;
|
||||
}
|
||||
else {
|
||||
L_sum = L->shadow_color * shadow;
|
||||
L_sum = L->shadow_background_color * L->shadow_throughput * shadow +
|
||||
L->shadow_radiance_sum;
|
||||
}
|
||||
return L_sum;
|
||||
}
|
||||
|
@@ -42,8 +42,6 @@
|
||||
#include "util/util_types.h"
|
||||
#include "util/util_texture.h"
|
||||
|
||||
#define ccl_restrict_ptr const * __restrict
|
||||
|
||||
#define ccl_addr_space
|
||||
|
||||
#define ccl_local_id(d) 0
|
||||
@@ -197,7 +195,7 @@ template<typename T> struct texture_image {
|
||||
if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
|
||||
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
/* Fall through. */
|
||||
ATTR_FALLTHROUGH;
|
||||
case EXTENSION_EXTEND:
|
||||
ix = wrap_clamp(ix, width);
|
||||
iy = wrap_clamp(iy, height);
|
||||
@@ -224,7 +222,7 @@ template<typename T> struct texture_image {
|
||||
if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
|
||||
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
/* Fall through. */
|
||||
ATTR_FALLTHROUGH;
|
||||
case EXTENSION_EXTEND:
|
||||
nix = wrap_clamp(ix+1, width);
|
||||
niy = wrap_clamp(iy+1, height);
|
||||
@@ -267,7 +265,7 @@ template<typename T> struct texture_image {
|
||||
if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
|
||||
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
/* Fall through. */
|
||||
ATTR_FALLTHROUGH;
|
||||
case EXTENSION_EXTEND:
|
||||
pix = wrap_clamp(ix-1, width);
|
||||
piy = wrap_clamp(iy-1, height);
|
||||
@@ -337,7 +335,7 @@ template<typename T> struct texture_image {
|
||||
{
|
||||
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
/* Fall through. */
|
||||
ATTR_FALLTHROUGH;
|
||||
case EXTENSION_EXTEND:
|
||||
ix = wrap_clamp(ix, width);
|
||||
iy = wrap_clamp(iy, height);
|
||||
@@ -376,7 +374,7 @@ template<typename T> struct texture_image {
|
||||
{
|
||||
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
/* Fall through. */
|
||||
ATTR_FALLTHROUGH;
|
||||
case EXTENSION_EXTEND:
|
||||
nix = wrap_clamp(ix+1, width);
|
||||
niy = wrap_clamp(iy+1, height);
|
||||
@@ -451,7 +449,7 @@ template<typename T> struct texture_image {
|
||||
{
|
||||
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
/* Fall through. */
|
||||
ATTR_FALLTHROUGH;
|
||||
case EXTENSION_EXTEND:
|
||||
pix = wrap_clamp(ix-1, width);
|
||||
piy = wrap_clamp(iy-1, height);
|
||||
|
@@ -55,7 +55,8 @@
|
||||
#define ccl_restrict __restrict__
|
||||
#define ccl_align(n) __align__(n)
|
||||
|
||||
#define ccl_restrict_ptr const * __restrict__
|
||||
#define ATTR_FALLTHROUGH
|
||||
|
||||
#define CCL_MAX_LOCAL_SIZE (CUDA_THREADS_BLOCK_WIDTH*CUDA_THREADS_BLOCK_WIDTH)
|
||||
|
||||
|
||||
|
@@ -50,7 +50,7 @@
|
||||
# define ccl_addr_space
|
||||
#endif
|
||||
|
||||
#define ccl_restrict_ptr const * __restrict__
|
||||
#define ATTR_FALLTHROUGH
|
||||
|
||||
#define ccl_local_id(d) get_local_id(d)
|
||||
#define ccl_global_id(d) get_global_id(d)
|
||||
|
@@ -175,15 +175,26 @@ ccl_device float cmj_sample_1D(int s, int N, int p)
|
||||
return (x + jx)*invN;
|
||||
}
|
||||
|
||||
/* TODO(sergey): Do some extra tests and consider moving to util_math.h. */
|
||||
ccl_device_inline int cmj_isqrt(int value)
|
||||
{
|
||||
#if defined(__KERNEL_CUDA__)
|
||||
return float_to_int(__fsqrt_ru(value));
|
||||
#elif defined(__KERNEL_GPU__)
|
||||
return float_to_int(sqrtf(value));
|
||||
#else
|
||||
/* This is a work around for fast-math on CPU which might replace sqrtf()
|
||||
* with am approximated version.
|
||||
*/
|
||||
return float_to_int(sqrtf(value) + 1e-6f);
|
||||
#endif
|
||||
}
|
||||
|
||||
ccl_device void cmj_sample_2D(int s, int N, int p, float *fx, float *fy)
|
||||
{
|
||||
kernel_assert(s < N);
|
||||
|
||||
#if defined(__KERNEL_CUDA__)
|
||||
int m = float_to_int(__fsqrt_ru(N));
|
||||
#else
|
||||
int m = float_to_int(sqrtf(N));
|
||||
#endif
|
||||
int m = cmj_isqrt(N);
|
||||
int n = (N - 1)/m + 1;
|
||||
float invN = 1.0f/N;
|
||||
float invm = 1.0f/m;
|
||||
|
@@ -142,7 +142,7 @@ ccl_device_inline void kernel_write_denoising_shadow(KernelGlobals *kg, ccl_glob
|
||||
|
||||
ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg,
|
||||
ShaderData *sd,
|
||||
ccl_global PathState *state,
|
||||
ccl_addr_space PathState *state,
|
||||
PathRadiance *L)
|
||||
{
|
||||
#ifdef __DENOISING_FEATURES__
|
||||
@@ -152,6 +152,11 @@ ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg,
|
||||
|
||||
L->denoising_depth += ensure_finite(state->denoising_feature_weight * sd->ray_length);
|
||||
|
||||
/* Skip implicitly transparent surfaces. */
|
||||
if(sd->flag & SD_HAS_ONLY_VOLUME) {
|
||||
return;
|
||||
}
|
||||
|
||||
float3 normal = make_float3(0.0f, 0.0f, 0.0f);
|
||||
float3 albedo = make_float3(0.0f, 0.0f, 0.0f);
|
||||
float sum_weight = 0.0f, sum_nonspecular_weight = 0.0f;
|
||||
@@ -356,7 +361,16 @@ ccl_device_inline void kernel_write_result(KernelGlobals *kg, ccl_global float *
|
||||
# endif
|
||||
if(kernel_data.film.pass_denoising_clean) {
|
||||
float3 noisy, clean;
|
||||
path_radiance_split_denoising(kg, L, &noisy, &clean);
|
||||
#ifdef __SHADOW_TRICKS__
|
||||
if(is_shadow_catcher) {
|
||||
noisy = L_sum;
|
||||
clean = make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
else
|
||||
#endif /* __SHADOW_TRICKS__ */
|
||||
{
|
||||
path_radiance_split_denoising(kg, L, &noisy, &clean);
|
||||
}
|
||||
kernel_write_pass_float3_variance(buffer + kernel_data.film.pass_denoising_data + DENOISING_PASS_COLOR,
|
||||
sample, noisy);
|
||||
kernel_write_pass_float3_unaligned(buffer + kernel_data.film.pass_denoising_clean,
|
||||
@@ -364,7 +378,7 @@ ccl_device_inline void kernel_write_result(KernelGlobals *kg, ccl_global float *
|
||||
}
|
||||
else {
|
||||
kernel_write_pass_float3_variance(buffer + kernel_data.film.pass_denoising_data + DENOISING_PASS_COLOR,
|
||||
sample, L_sum);
|
||||
sample, ensure_finite3(L_sum));
|
||||
}
|
||||
|
||||
kernel_write_pass_float3_variance(buffer + kernel_data.film.pass_denoising_data + DENOISING_PASS_NORMAL,
|
||||
|
@@ -407,7 +407,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
|
||||
}
|
||||
#endif /* __SUBSURFACE__ */
|
||||
|
||||
#if defined(__EMISSION__) && defined(__BRANCHED_PATH__)
|
||||
#if defined(__EMISSION__)
|
||||
if(kernel_data.integrator.use_direct_light) {
|
||||
int all = (kernel_data.integrator.sample_all_lights_indirect) ||
|
||||
(state->flag & PATH_RAY_SHADOW_CATCHER);
|
||||
@@ -421,7 +421,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
|
||||
L,
|
||||
all);
|
||||
}
|
||||
#endif /* defined(__EMISSION__) && defined(__BRANCHED_PATH__) */
|
||||
#endif /* defined(__EMISSION__) */
|
||||
|
||||
if(!kernel_path_surface_bounce(kg, rng, sd, &throughput, state, L, ray))
|
||||
break;
|
||||
@@ -643,11 +643,16 @@ ccl_device_inline float kernel_path_integrate(KernelGlobals *kg,
|
||||
#ifdef __SHADOW_TRICKS__
|
||||
if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) {
|
||||
if(state.flag & PATH_RAY_CAMERA) {
|
||||
state.flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY | PATH_RAY_STORE_SHADOW_INFO);
|
||||
state.flag |= (PATH_RAY_SHADOW_CATCHER |
|
||||
PATH_RAY_SHADOW_CATCHER_ONLY |
|
||||
PATH_RAY_STORE_SHADOW_INFO);
|
||||
state.catcher_object = sd.object;
|
||||
if(!kernel_data.background.transparent) {
|
||||
L->shadow_color = indirect_background(kg, &emission_sd, &state, &ray);
|
||||
L->shadow_background_color =
|
||||
indirect_background(kg, &emission_sd, &state, &ray);
|
||||
}
|
||||
L->shadow_radiance_sum = path_radiance_clamp_and_sum(kg, L);
|
||||
L->shadow_throughput = average(throughput);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@@ -499,13 +499,16 @@ ccl_device float kernel_branched_path_integrate(KernelGlobals *kg,
|
||||
|
||||
#ifdef __SHADOW_TRICKS__
|
||||
if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) {
|
||||
if(state.flag & PATH_RAY_CAMERA) {
|
||||
state.flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY | PATH_RAY_STORE_SHADOW_INFO);
|
||||
state.catcher_object = sd.object;
|
||||
if(!kernel_data.background.transparent) {
|
||||
L->shadow_color = indirect_background(kg, &emission_sd, &state, &ray);
|
||||
}
|
||||
state.flag |= (PATH_RAY_SHADOW_CATCHER |
|
||||
PATH_RAY_SHADOW_CATCHER_ONLY |
|
||||
PATH_RAY_STORE_SHADOW_INFO);
|
||||
state.catcher_object = sd.object;
|
||||
if(!kernel_data.background.transparent) {
|
||||
L->shadow_background_color =
|
||||
indirect_background(kg, &emission_sd, &state, &ray);
|
||||
}
|
||||
L->shadow_radiance_sum = path_radiance_clamp_and_sum(kg, L);
|
||||
L->shadow_throughput = average(throughput);
|
||||
}
|
||||
else {
|
||||
state.flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
|
||||
|
@@ -139,9 +139,11 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta
|
||||
/* random number generator next bounce */
|
||||
state->rng_offset += PRNG_BOUNCE_NUM;
|
||||
|
||||
#ifdef __DENOISING_FEATURES__
|
||||
if((state->denoising_feature_weight == 0.0f) && !(state->flag & PATH_RAY_SHADOW_CATCHER)) {
|
||||
state->flag &= ~PATH_RAY_STORE_SHADOW_INFO;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, PathState *state)
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
#if defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__) || defined(__SHADOW_TRICKS__)
|
||||
#if defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__) || defined(__SHADOW_TRICKS__) || defined(__BAKING__)
|
||||
/* branched path tracing: connect path directly to position on one or more lights and add it to L */
|
||||
ccl_device_noinline void kernel_branched_path_surface_connect_light(
|
||||
KernelGlobals *kg,
|
||||
|
@@ -128,6 +128,21 @@ ccl_device unsigned int get_global_queue_index(
|
||||
return my_gqidx;
|
||||
}
|
||||
|
||||
ccl_device int dequeue_ray_index(
|
||||
int queue_number,
|
||||
ccl_global int *queues,
|
||||
int queue_size,
|
||||
ccl_global int *queue_index)
|
||||
{
|
||||
int index = atomic_fetch_and_dec_uint32((ccl_global uint*)&queue_index[queue_number])-1;
|
||||
|
||||
if(index < 0) {
|
||||
return QUEUE_EMPTY_SLOT;
|
||||
}
|
||||
|
||||
return queues[index + queue_number * queue_size];
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif // __KERNEL_QUEUE_H__
|
||||
|
@@ -418,7 +418,7 @@ ccl_device_noinline void subsurface_scatter_multi_setup(
|
||||
}
|
||||
|
||||
/* subsurface scattering step, from a point on the surface to another nearby point on the same object */
|
||||
ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_global PathState *state,
|
||||
ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state,
|
||||
int state_flag, ShaderClosure *sc, uint *lcg_state, float disk_u, float disk_v, bool all)
|
||||
{
|
||||
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
@@ -479,6 +479,10 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_g
|
||||
if(ss_isect.num_hits > 0) {
|
||||
float3 origP = sd->P;
|
||||
|
||||
/* Workaround for AMD GPU OpenCL compiler. Most probably cache bypass issue. */
|
||||
#if defined(__SPLIT_KERNEL__) && defined(__KERNEL_OPENCL_AMD__) && defined(__KERNEL_GPU__)
|
||||
kernel_split_params.dummy_sd_flag = sd->flag;
|
||||
#endif
|
||||
/* setup new shading point */
|
||||
shader_setup_from_subsurface(kg, sd, &ss_isect.hits[0], &ray);
|
||||
|
||||
|
@@ -82,10 +82,10 @@ KERNEL_TEX(uint, texture_uint, __sobol_directions)
|
||||
# if __CUDA_ARCH__ < 300
|
||||
/* full-float image */
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_000)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_001)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_002)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_003)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_004)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_008)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_016)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_024)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float4_032)
|
||||
|
||||
KERNEL_IMAGE_TEX(float4, texture_image3d_float4, __tex_image_float4_3d_000)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image3d_float4, __tex_image_float4_3d_001)
|
||||
@@ -93,91 +93,93 @@ KERNEL_IMAGE_TEX(float4, texture_image3d_float4, __tex_image_float4_3d_002)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image3d_float4, __tex_image_float4_3d_003)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image3d_float4, __tex_image_float4_3d_004)
|
||||
|
||||
/* image */
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_005)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_006)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_007)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_008)
|
||||
/* image
|
||||
* These texture names are encoded to their flattened slots as
|
||||
* ImageManager::type_index_to_flattened_slot() returns them. */
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_001)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_009)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_010)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_011)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_012)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_013)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_014)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_015)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_016)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_017)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_018)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_019)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_020)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_021)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_022)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_023)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_024)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_025)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_026)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_027)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_028)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_029)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_030)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_031)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_032)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_033)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_034)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_035)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_036)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_037)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_038)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_039)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_040)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_041)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_042)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_043)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_044)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_045)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_046)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_047)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_048)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_049)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_050)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_051)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_052)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_053)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_054)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_055)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_056)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_057)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_058)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_059)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_060)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_061)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_062)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_063)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_064)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_065)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_066)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_067)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_068)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_069)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_070)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_071)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_072)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_073)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_074)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_075)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_076)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_077)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_078)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_079)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_080)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_081)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_082)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_083)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_084)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_085)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_086)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_087)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_088)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_089)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_097)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_105)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_113)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_121)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_129)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_137)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_145)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_153)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_161)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_169)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_177)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_185)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_193)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_201)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_209)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_217)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_225)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_233)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_241)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_249)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_257)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_265)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_273)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_281)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_289)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_297)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_305)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_313)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_321)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_329)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_337)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_345)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_353)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_361)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_369)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_377)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_385)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_393)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_401)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_409)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_417)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_425)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_433)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_441)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_449)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_457)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_465)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_473)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_481)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_489)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_497)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_505)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_513)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_521)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_529)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_537)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_545)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_553)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_561)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_569)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_577)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_585)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_593)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_601)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_609)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_617)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_625)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_633)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_641)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_649)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_657)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_665)
|
||||
|
||||
# else
|
||||
/* bindless textures */
|
||||
|
@@ -124,17 +124,19 @@ CCL_NAMESPACE_BEGIN
|
||||
# define __VOLUME_SCATTER__
|
||||
# define __SHADOW_RECORD_ALL__
|
||||
# define __CMJ__
|
||||
# define __BRANCHED_PATH__
|
||||
# endif /* __KERNEL_OPENCL_NVIDIA__ */
|
||||
|
||||
# ifdef __KERNEL_OPENCL_APPLE__
|
||||
# define __KERNEL_SHADING__
|
||||
# define __KERNEL_ADV_SHADING__
|
||||
# define __PRINCIPLED__
|
||||
# define __CMJ__
|
||||
/* TODO(sergey): Currently experimental section is ignored here,
|
||||
* this is because megakernel in device_opencl does not support
|
||||
* custom cflags depending on the scene features.
|
||||
*/
|
||||
# endif /* __KERNEL_OPENCL_NVIDIA__ */
|
||||
# endif /* __KERNEL_OPENCL_APPLE__ */
|
||||
|
||||
# ifdef __KERNEL_OPENCL_AMD__
|
||||
# define __CL_USE_NATIVE__
|
||||
@@ -153,6 +155,7 @@ CCL_NAMESPACE_BEGIN
|
||||
# define __CL_USE_NATIVE__
|
||||
# define __KERNEL_SHADING__
|
||||
# define __KERNEL_ADV_SHADING__
|
||||
# define __PRINCIPLED__
|
||||
# define __CMJ__
|
||||
# endif /* __KERNEL_OPENCL_INTEL_CPU__ */
|
||||
|
||||
@@ -235,6 +238,9 @@ CCL_NAMESPACE_BEGIN
|
||||
#ifdef __NO_PRINCIPLED__
|
||||
# undef __PRINCIPLED__
|
||||
#endif
|
||||
#ifdef __NO_DENOISING__
|
||||
# undef __DENOISING_FEATURES__
|
||||
#endif
|
||||
|
||||
/* Random Numbers */
|
||||
|
||||
@@ -511,7 +517,13 @@ typedef ccl_addr_space struct PathRadiance {
|
||||
float3 path_total_shaded;
|
||||
|
||||
/* Color of the background on which shadow is alpha-overed. */
|
||||
float3 shadow_color;
|
||||
float3 shadow_background_color;
|
||||
|
||||
/* Path radiance sum and throughput at the moment when ray hits shadow
|
||||
* catcher object.
|
||||
*/
|
||||
float3 shadow_radiance_sum;
|
||||
float shadow_throughput;
|
||||
#endif
|
||||
|
||||
#ifdef __DENOISING_FEATURES__
|
||||
@@ -1386,6 +1398,8 @@ enum QueueNumber {
|
||||
#ifdef __BRANCHED_PATH__
|
||||
/* All rays moving to next iteration of the indirect loop for light */
|
||||
QUEUE_LIGHT_INDIRECT_ITER,
|
||||
/* Queue of all inactive rays. These are candidates for sharing work of indirect loops */
|
||||
QUEUE_INACTIVE_RAYS,
|
||||
# ifdef __VOLUME__
|
||||
/* All rays moving to next iteration of the indirect loop for volumes */
|
||||
QUEUE_VOLUME_INDIRECT_ITER,
|
||||
@@ -1428,6 +1442,9 @@ enum RayState {
|
||||
RAY_BRANCHED_VOLUME_INDIRECT = (1 << 5),
|
||||
RAY_BRANCHED_SUBSURFACE_INDIRECT = (1 << 6),
|
||||
RAY_BRANCHED_INDIRECT = (RAY_BRANCHED_LIGHT_INDIRECT | RAY_BRANCHED_VOLUME_INDIRECT | RAY_BRANCHED_SUBSURFACE_INDIRECT),
|
||||
|
||||
/* Ray is evaluating an iteration of an indirect loop for another thread */
|
||||
RAY_BRANCHED_INDIRECT_SHARED = (1 << 7),
|
||||
};
|
||||
|
||||
#define ASSIGN_RAY_STATE(ray_state, ray_index, state) (ray_state[ray_index] = ((ray_state[ray_index] & RAY_FLAG_MASK) | state))
|
||||
|
@@ -660,6 +660,7 @@ typedef struct VolumeSegment {
|
||||
* but the entire segment is needed to do always scattering, rather than probabilistically
|
||||
* hitting or missing the volume. if we don't know the transmittance at the end of the
|
||||
* volume we can't generate stratified distance samples up to that transmittance */
|
||||
#ifdef __VOLUME_DECOUPLED__
|
||||
ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *state,
|
||||
Ray *ray, ShaderData *sd, VolumeSegment *segment, bool heterogeneous)
|
||||
{
|
||||
@@ -829,6 +830,7 @@ ccl_device void kernel_volume_decoupled_free(KernelGlobals *kg, VolumeSegment *s
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif /* __VOLUME_DECOUPLED__ */
|
||||
|
||||
/* scattering for homogeneous and heterogeneous volumes, using decoupled ray
|
||||
* marching.
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2013 Blender Foundation
|
||||
* Copyright 2011-2017 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user