blender/intern/cycles/kernel/osl/nodes/node_mix.osl
Ton Roosendaal da376e0237 Cycles render engine, initial commit. This is the engine itself, blender modifications and build instructions will follow later.
Cycles uses code from some great open source projects, many thanks them:

* BVH building and traversal code from NVidia's "Understanding the Efficiency of Ray Traversal on GPUs":
http://code.google.com/p/understanding-the-efficiency-of-ray-traversal-on-gpus/
* Open Shading Language for a large part of the shading system:
http://code.google.com/p/openshadinglanguage/
* Blender for procedural textures and a few other nodes.
* Approximate Catmull Clark subdivision from NVidia Mesh tools:
http://code.google.com/p/nvidia-mesh-tools/
* Sobol direction vectors from:
http://web.maths.unsw.edu.au/~fkuo/sobol/
* Film response functions from:
http://www.cs.columbia.edu/CAVE/software/softlib/dorf.php
2011-04-27 11:58:34 +00:00

389 lines
7.8 KiB
Plaintext

/*
* Copyright 2011, Blender Foundation.
*
* 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.
*/
#include "stdosl.h"
color rgb_to_hsv(color rgb)
{
float cmax, cmin, h, s, v, cdelta;
color c;
cmax = max(rgb[0], max(rgb[1], rgb[2]));
cmin = min(rgb[0], min(rgb[1], rgb[2]));
cdelta = cmax - cmin;
v = cmax;
if(cmax != 0.0) {
s = cdelta/cmax;
}
else {
s = 0.0;
h = 0.0;
}
if(s == 0.0) {
h = 0.0;
}
else {
c = (color(cmax, cmax, cmax) - rgb)/cdelta;
if(rgb[0] == cmax) h = c[2] - c[1];
else if(rgb[1] == cmax) h = 2.0 + c[0] - c[2];
else h = 4.0 + c[1] - c[0];
h /= 6.0;
if(h < 0.0)
h += 1.0;
}
return color(h, s, v);
}
color hsv_to_rgb(color hsv)
{
float i, f, p, q, t, h, s, v;
color rgb;
h = hsv[0];
s = hsv[1];
v = hsv[2];
if(s==0.0) {
rgb = color(v, v, v);
}
else {
if(h==1.0)
h = 0.0;
h *= 6.0;
i = floor(h);
f = h - i;
rgb = color(f, f, f);
p = v*(1.0-s);
q = v*(1.0-(s*f));
t = v*(1.0-(s*(1.0-f)));
if(i == 0.0) rgb = color(v, t, p);
else if(i == 1.0) rgb = color(q, v, p);
else if(i == 2.0) rgb = color(p, v, t);
else if(i == 3.0) rgb = color(p, q, v);
else if(i == 4.0) rgb = color(t, p, v);
else rgb = color(v, p, q);
}
return rgb;
}
color node_mix_blend(float t, color col1, color col2)
{
return mix(col1, col2, t);
}
color node_mix_add(float t, color col1, color col2)
{
return mix(col1, col1 + col2, t);
}
color node_mix_mul(float t, color col1, color col2)
{
return mix(col1, col1 * col2, t);
}
color node_mix_screen(float t, color col1, color col2)
{
float tm = 1.0 - t;
return color(1.0) - (color(tm) + t*(color(1.0) - col2))*(color(1.0) - col1);
}
color node_mix_overlay(float t, color col1, color col2)
{
float tm = 1.0 - t;
color outcol = col1;
if(outcol[0] < 0.5)
outcol[0] *= tm + 2.0*t*col2[0];
else
outcol[0] = 1.0 - (tm + 2.0*t*(1.0 - col2[0]))*(1.0 - outcol[0]);
if(outcol[1] < 0.5)
outcol[1] *= tm + 2.0*t*col2[1];
else
outcol[1] = 1.0 - (tm + 2.0*t*(1.0 - col2[1]))*(1.0 - outcol[1]);
if(outcol[2] < 0.5)
outcol[2] *= tm + 2.0*t*col2[2];
else
outcol[2] = 1.0 - (tm + 2.0*t*(1.0 - col2[2]))*(1.0 - outcol[2]);
return outcol;
}
color node_mix_sub(float t, color col1, color col2)
{
return mix(col1, col1 - col2, t);
}
color node_mix_div(float t, color col1, color col2)
{
float tm = 1.0 - t;
color outcol = col1;
if(col2[0] != 0.0) outcol[0] = tm*outcol[0] + t*outcol[0]/col2[0];
if(col2[1] != 0.0) outcol[1] = tm*outcol[1] + t*outcol[1]/col2[1];
if(col2[2] != 0.0) outcol[2] = tm*outcol[2] + t*outcol[2]/col2[2];
return outcol;
}
color node_mix_diff(float t, color col1, color col2)
{
return mix(col1, abs(col1 - col2), t);
}
color node_mix_dark(float t, color col1, color col2)
{
return min(col1, col2*t);
}
color node_mix_light(float t, color col1, color col2)
{
return max(col1, col2*t);
}
color node_mix_dodge(float t, color col1, color col2)
{
color outcol = col1;
if(outcol[0] != 0.0) {
float tmp = 1.0 - t*col2[0];
if(tmp <= 0.0)
outcol[0] = 1.0;
else if((tmp = outcol[0]/tmp) > 1.0)
outcol[0] = 1.0;
else
outcol[0] = tmp;
}
if(outcol[1] != 0.0) {
float tmp = 1.0 - t*col2[1];
if(tmp <= 0.0)
outcol[1] = 1.0;
else if((tmp = outcol[1]/tmp) > 1.0)
outcol[1] = 1.0;
else
outcol[1] = tmp;
}
if(outcol[2] != 0.0) {
float tmp = 1.0 - t*col2[2];
if(tmp <= 0.0)
outcol[2] = 1.0;
else if((tmp = outcol[2]/tmp) > 1.0)
outcol[2] = 1.0;
else
outcol[2] = tmp;
}
return outcol;
}
color node_mix_burn(float t, color col1, color col2)
{
float tmp, tm = 1.0 - t;
color outcol = col1;
tmp = tm + t*col2[0];
if(tmp <= 0.0)
outcol[0] = 0.0;
else if((tmp = (1.0 - (1.0 - outcol[0])/tmp)) < 0.0)
outcol[0] = 0.0;
else if(tmp > 1.0)
outcol[0] = 1.0;
else
outcol[0] = tmp;
tmp = tm + t*col2[1];
if(tmp <= 0.0)
outcol[1] = 0.0;
else if((tmp = (1.0 - (1.0 - outcol[1])/tmp)) < 0.0)
outcol[1] = 0.0;
else if(tmp > 1.0)
outcol[1] = 1.0;
else
outcol[1] = tmp;
tmp = tm + t*col2[2];
if(tmp <= 0.0)
outcol[2] = 0.0;
else if((tmp = (1.0 - (1.0 - outcol[2])/tmp)) < 0.0)
outcol[2] = 0.0;
else if(tmp > 1.0)
outcol[2] = 1.0;
else
outcol[2] = tmp;
return outcol;
}
color node_mix_hue(float t, color col1, color col2)
{
color outcol = col1;
color hsv2 = rgb_to_hsv(col2);
if(hsv2[1] != 0.0) {
color hsv = rgb_to_hsv(outcol);
hsv[0] = hsv2[0];
color tmp = hsv_to_rgb(hsv);
outcol = mix(outcol, tmp, t);
}
return outcol;
}
color node_mix_sat(float t, color col1, color col2)
{
float tm = 1.0 - t;
color outcol = col1;
color hsv = rgb_to_hsv(outcol);
if(hsv[1] != 0.0) {
color hsv2 = rgb_to_hsv(col2);
hsv[1] = tm*hsv[1] + t*hsv2[1];
outcol = hsv_to_rgb(hsv);
}
return outcol;
}
color node_mix_val(float t, color col1, color col2)
{
float tm = 1.0 - t;
color hsv = rgb_to_hsv(col1);
color hsv2 = rgb_to_hsv(col2);
hsv[2] = tm*hsv[2] + t*hsv2[2];
return hsv_to_rgb(hsv);
}
color node_mix_color(float t, color col1, color col2)
{
color outcol = col1;
color hsv2 = rgb_to_hsv(col2);
if(hsv2[1] != 0.0) {
color hsv = rgb_to_hsv(outcol);
hsv[0] = hsv2[0];
hsv[1] = hsv2[1];
color tmp = hsv_to_rgb(hsv);
outcol = mix(outcol, tmp, t);
}
return outcol;
}
color node_mix_soft(float t, color col1, color col2)
{
float tm = 1.0 - t;
color one= color(1.0);
color scr= one - (one - col2)*(one - col1);
return tm*col1 + t*((one - col1)*col2*col1 + col1*scr);
}
color node_mix_linear(float t, color col1, color col2)
{
color outcol = col1;
if(col2[0] > 0.5)
outcol[0]= col1[0] + t*(2.0*(col2[0] - 0.5));
else
outcol[0]= col1[0] + t*(2.0*(col2[0]) - 1.0);
if(col2[1] > 0.5)
outcol[1]= col1[1] + t*(2.0*(col2[1] - 0.5));
else
outcol[1]= col1[1] + t*(2.0*(col2[1]) - 1.0);
if(col2[2] > 0.5)
outcol[2]= col1[2] + t*(2.0*(col2[2] - 0.5));
else
outcol[2]= col1[2] + t*(2.0*(col2[2]) - 1.0);
return outcol;
}
shader node_mix(
string type = "Mix",
float Fac = 0.5,
color Color1 = color(0.0, 0.0, 0.0),
color Color2 = color(0.0, 0.0, 0.0),
output color Color = color(0.0, 0.0, 0.0))
{
float t = clamp(Fac, 0.0, 1.0);
if(type == "Mix")
Color = node_mix_blend(t, Color1, Color2);
if(type == "Add")
Color = node_mix_add(t, Color1, Color2);
if(type == "Multiply")
Color = node_mix_mul(t, Color1, Color2);
if(type == "Screen")
Color = node_mix_screen(t, Color1, Color2);
if(type == "Overlay")
Color = node_mix_overlay(t, Color1, Color2);
if(type == "Subtract")
Color = node_mix_sub(t, Color1, Color2);
if(type == "Divide")
Color = node_mix_div(t, Color1, Color2);
if(type == "Difference")
Color = node_mix_diff(t, Color1, Color2);
if(type == "Darken")
Color = node_mix_dark(t, Color1, Color2);
if(type == "Lighten")
Color = node_mix_light(t, Color1, Color2);
if(type == "Dodge")
Color = node_mix_dodge(t, Color1, Color2);
if(type == "Burn")
Color = node_mix_burn(t, Color1, Color2);
if(type == "Hue")
Color = node_mix_hue(t, Color1, Color2);
if(type == "Saturation")
Color = node_mix_sat(t, Color1, Color2);
if(type == "Value")
Color = node_mix_val (t, Color1, Color2);
if(type == "Color")
Color = node_mix_color(t, Color1, Color2);
if(type == "Soft Light")
Color = node_mix_soft(t, Color1, Color2);
if(type == "Linear Light")
Color = node_mix_linear(t, Color1, Color2);
}