<p>As suggested in the comments, I created an exact scene in Blender using the same .obj. After adding a mix shader node and setting one side to diffuse and the other to a perfect mirror, you can see that the results are almost identical. This would indicate that my implementation is correct.</p>

<p>Here is a side by side comparison. Mine is on the left, Blender's is on the right:</p>

<p><a href="https://i.sstatic.net/qWziH.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/qWziH.png" alt="enter image description here"></a></p>

CC BY-SA 3.0
2017-01-06T16:10:43.373Z
2017-01-06T16:10:43.373Z
Henry Bergin
<p>I apologize if my methods seem way off because this is my first time trying to build a path tracer and I'm struggling quite a bit. Currently, I am trying to mimic the "mix shader" node in Blender 3D that combines two different shaders. I would like to add this functionality to my path tracer because it would allow me to make a plastic-like material. Reading through a few explanations, it seems it takes a probabilistic approach to picking one or the other when a ray hits the surface.</p>

<p>Here is a rendering of an object with a 50/50 mix of ideal reflection and ideal diffuse at 80 samples per pixel:
<a href="https://i.sstatic.net/yAi7i.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/yAi7i.png" alt="enter image description here"></a>   </p>

<p>Something is just off about it. Especially those weird underside highlights on the leg extending farthest to the left. I have a strong feeling I'm implementing it wrong.</p>

<p>Here is a pseudo implementation of the path tracing part. It uses explicit light sampling. Based off of smallpt path tracer.</p>

<pre><code>rayColor(ray r, depth, int E=1)
{
    if(r doesn't hit triangle)
        return 0
    if(r hit is a light)
    {
       if(E)
         return light_emission
       else
         return 0
    }

    vector x = r.origin + r.direction*t // x is point where r hit tri
    vector n = normal where ray hit triangle
    n.normalize()
    vector nl = n.dot(r.d) &lt; 0 ? n : n*(-1) // properly orient normal

    if(++depth &gt; 5) return 0 // max bounces

    float triangle_area   = area of emitting triangle
    vector x_light_random = random point on emitting triangle
    vector light_normal   = normal of emitting triangle

    vector d = x_light_random = x_converted;


    if(light_normal.dot(d) &gt; 0) light_normal *= -1; // make it emit
                                                    // both sides

    object_normal.normalize();
    light_normal.normalize();

    BRDF = 1/PI // perfect diffuse
    light_emitted = 1 // emission of 1
    vector light_out = 0
    if(ray starting at x towards d hits light (i.e. not in shadow))
    {
         light_out = BRDF*light_emitted*(object_normal.dot(d))*
                            (-1*light_normal.dot(d)*triangle_area)/
                            (d.length*d.length*d.length*d.length)
    }
    vector direct_light = color_of_object_triangle*light_out;



  //----SPECULAR-----
  vector d2 = r.dir-n*2*n.dot(r.dir); // ideal reflection
  vector light_color = 1 // white since dialectics don't change spec
  vector specular = light_color*rayColor(createRay(x, d2),depth)

  float P = 0.5; // 50/50 chance of mirror/diffuse
  if(erand(Xi) &lt; P)
      return direct_light/P
  else
      return spec/(1-P)
</code></pre>

<p>Thank you to anyone who can offer me some direction! Again, sorry if this is really convoluted. I've made it so far and I'm about to give up, but I feel like I'm reaaaally close. </p>

CC BY-SA 3.0
2017-01-06T05:47:28.517Z
Do you have a reference picture of the image you expect to get? It could be easier to first replicate an exiting image and compare your result.
Julien Guertault
CC BY-SA 3.0
2017-01-06T06:32:27.000Z
@JulienGuertault thank you so much for the suggestion! That was brilliant and I wish I had thought of it earlier. That would've helped with a lot of hair pulling. See my edited post. T
Henry Bergin
CC BY-SA 3.0
2017-01-07T12:20:26.467Z
I've edited out the "one more thing" section now that you've posted it as a separate question. Notice that the separate question now appears in the "Linked" section on the right hand side of this page, because that question contains a link to this question.
trichoplax is on Codidact now
CC BY-SA 3.0
2017-01-07T18:30:39.693Z
In case it's helpful, here's a good short read about path tracing basics with some simple c++ source code accompany it: http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/
Alan Wolfe
<rendering><raytracing><shader><3d><pathtracing>
Mix shader looks wrong on my path tracer
Henry Bergin
# Mix shader looks wrong on my path tracer

(Asked by: username_0 on 2017-01-06)

I apologize if my methods seem way off because this is my first time trying to build a path tracer and I'm struggling quite a bit. Currently, I am trying to mimic the "mix shader" node in Blender 3D that combines two different shaders. I would like to add this functionality to my path tracer because it would allow me to make a plastic-like material. Reading through a few explanations, it seems it takes a probabilistic approach to picking one or the other when a ray hits the surface.

Here is a rendering of an object with a 50/50 mix of ideal reflection and ideal diffuse at 80 samples per pixel:
[![enter image description here](https://i.sstatic.net/yAi7i.png)](https://i.sstatic.net/yAi7i.png)

Something is just off about it. Especially those weird underside highlights on the leg extending farthest to the left. I have a strong feeling I'm implementing it wrong.

Here is a pseudo implementation of the path tracing part. It uses explicit light sampling. Based off of smallpt path tracer.

```
rayColor(ray r, depth, int E=1)
{
    if(r doesn't hit triangle)
        return 0
    if(r hit is a light)
    {
       if(E)
         return light_emission
       else
         return 0
    }

    vector x = r.origin + r.direction*t // x is point where r hit tri
    vector n = normal where ray hit triangle
    n.normalize()
    vector nl = n.dot(r.d) < 0 ? n : n*(-1) // properly orient normal

    if(++depth > 5) return 0 // max bounces

    float triangle_area   = area of emitting triangle
    vector x_light_random = random point on emitting triangle
    vector light_normal   = normal of emitting triangle

    vector d = x_light_random = x_converted;

    if(light_normal.dot(d) > 0) light_normal *= -1; // make it emit
                                                    // both sides

    object_normal.normalize();
    light_normal.normalize();

    BRDF = 1/PI // perfect diffuse
    light_emitted = 1 // emission of 1
    vector light_out = 0
    if(ray starting at x towards d hits light (i.e. not in shadow))
    {
         light_out = BRDF*light_emitted*(object_normal.dot(d))*
                            (-1*light_normal.dot(d)*triangle_area)/
                            (d.length*d.length*d.length*d.length)
    }
    vector direct_light = color_of_object_triangle*light_out;

  //----SPECULAR-----
  vector d2 = r.dir-n*2*n.dot(r.dir); // ideal reflection
  vector light_color = 1 // white since dialectics don't change spec
  vector specular = light_color*rayColor(createRay(x, d2),depth)

  float P = 0.5; // 50/50 chance of mirror/diffuse
  if(erand(Xi) < P)
      return direct_light/P
  else
      return spec/(1-P)

```

Thank you to anyone who can offer me some direction! Again, sorry if this is really convoluted. I've made it so far and I'm about to give up, but I feel like I'm reaaaally close.

**Tags:** rendering, raytracing, shader, 3d, pathtracing

> **Comments:**
> **username_1**: Do you have a reference picture of the image you expect to get? It could be easier to first replicate an exiting image and compare your result.  
> **username_0**: @username_1 thank you so much for the suggestion! That was brilliant and I wish I had thought of it earlier. That would've helped with a lot of hair pulling. See my edited post. T  
> **username_2**: I've edited out the "one more thing" section now that you've posted it as a separate question. Notice that the separate question now appears in the "Linked" section on the right hand side of this page, because that question contains a link to this question.  
> **username_3**: In case it's helpful, here's a good short read about path tracing basics with some simple c++ source code accompany it: http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse-and-emissive/  

---

## 1 answers

### Answer by username_0 on 2017-01-06. Score: 4

As suggested in the comments, I created an exact scene in Blender using the same .obj. After adding a mix shader node and setting one side to diffuse and the other to a perfect mirror, you can see that the results are almost identical. This would indicate that my implementation is correct.

Here is a side by side comparison. Mine is on the left, Blender's is on the right:

[![enter image description here](https://i.sstatic.net/qWziH.png)](https://i.sstatic.net/qWziH.png)


---

