Exemple #1
0
    // 基于斜率的办法避免不了精度误差

    /*
     * List<FragmentIn> Rast(FragmentIn v1, FragmentIn v2, FragmentIn v3) {
     *  var frags = new List<FragmentIn>();
     *
     *  var vv1 = v1;
     *  var vv2 = v2;
     *  var vv3 = v3;
     *
     *  // 保证v1,v2,v3 y轴依次变小
     *  if (v1.vertex.y < v2.vertex.y) Swap(ref v1, ref v2);
     *  if (v1.vertex.y < v3.vertex.y) Swap(ref v1, ref v3);
     *  if (v2.vertex.y < v3.vertex.y) Swap(ref v2, ref v3);
     *
     *  var p1 = v1.vertex;
     *  var p2 = v2.vertex;
     *  var p3 = v3.vertex;
     *
     *  if (p2.y == p3.y) {
     *      RastTriangle(v2, v3, v1, frags);
     *  }
     *  else if (p1.y == p2.y) {
     *      RastTriangle(v1, v2, v3, frags);
     *  }
     *  else {
     *      // y = y0 + k(x-x0)
     *      // x = x0 + 1/k*(y-y0)
     *      // 注意斜率为0或无穷大的情况
     *      float k = (p1.y - p3.y) / (p1.x - p3.x);
     *      float splitx;
     *      float splity;
     *
     *      if (p1.x != p3.x) {
     *          splitx = p3.x + (p2.y - p3.y) / k;
     *          splity = p2.y;
     *      } else {
     *          splitx = p3.x;
     *          splity = p2.y;
     *      }
     *
     *      var splitv = new FragmentIn();
     *      splitv.pixelx = (int)splitx;
     *      splitv.pixely = (int)splity;
     *
     *      LerpFragment(v1, v2, v3, splitv);
     *
     *      RastTriangle(v2, splitv, v1, frags);
     *      RastTriangle(v2, splitv, v3, frags);
     *  }
     *
     *  return frags;
     * }
     *
     * // 扫描线
     * //   /\3
     * // 1----2
     * void RastTriangle(FragmentIn v1, FragmentIn v2, FragmentIn v3, List<FragmentIn> frags) {
     *
     *  var p1 = v1.vertex;
     *  var p2 = v2.vertex;
     *  var p3 = v3.vertex;
     *
     *
     *  float curx1 = p1.x;
     *  float curx2 = p2.x;
     *  int inc = p1.y > p3.y ? -1 : 1;
     *
     *  int scanline = (int)p1.y;
     *  int scanto = (int)p3.y;
     *  if (scanline == scanto) {
     *      //三角形退化
     *
     *      curx1 = Mathf.Min(Mathf.Max(curx1, 0), width);
     *      curx2 = Mathf.Min(Mathf.Max(curx2, 0), width);
     *
     *      var ix1 = (int)curx1;
     *      var ix2 = (int)curx2;
     *      if (ix1 == ix2) {
     *          var frag = new FragmentIn();
     *          frag.pixelx = ix1;
     *          frag.pixely = scanline;
     *
     *          LerpFragment(v1, v2, v3, frag);
     *
     *          frags.Add(frag);
     *      }
     *      else {
     *          var incx = ix1 > ix2 ? -1 : 1;
     *          for (int x = ix1; x != ix2; x += incx) {
     *              var frag = new FragmentIn();
     *              frag.pixelx = x;
     *              frag.pixely = scanline;
     *
     *              LerpFragment(v1, v2, v3, frag);
     *
     *              frags.Add(frag);
     *          }
     *      }
     *  }
     *  else {
     *      float slop1 = (p3.x - p1.x)/(p3.y - p1.y);
     *      float slop2 = (p3.x - p2.x)/(p3.y - p2.y);
     *
     *      for (; scanline != scanto; scanline += inc) {
     *
     *          curx1 = Mathf.Min(Mathf.Max(curx1, 0), width);
     *          curx2 = Mathf.Min(Mathf.Max(curx2, 0), width);
     *
     *          var ix1 = (int)curx1;
     *          var ix2 = (int)curx2;
     *          if (ix1 == ix2) {
     *              var frag = new FragmentIn();
     *              frag.pixelx = ix1;
     *              frag.pixely = scanline;
     *
     *              LerpFragment(v1, v2, v3, frag);
     *
     *              frags.Add(frag);
     *          } else {
     *              var incx = ix1 > ix2 ? -1 : 1;
     *
     *              for (int x = ix1; x != ix2; x += incx) {
     *
     *                  var frag = new FragmentIn();
     *                  frag.pixelx = x;
     *                  frag.pixely = scanline;
     *
     *                  LerpFragment(v1, v2, v3, frag);
     *
     *                  frags.Add(frag);
     *              }
     *          }
     *
     *          curx1 += inc * slop1;
     *          curx2 += inc * slop2;
     *      }
     *  }
     * }
     */

    // 基于三角形面积做插值
    bool LerpFragment(FragmentIn v1, FragmentIn v2, FragmentIn v3, FragmentIn ret)
    {
        var v0  = new Vector4(ret.pixelx, ret.pixely);
        var d01 = v0 - v1.vertex;

        var d21 = v2.vertex - v1.vertex;
        var d31 = v3.vertex - v1.vertex;

        var denom = Mathf.Abs(d21.x * d31.y - d21.y * d31.x);

        if (denom < 0.000001)
        {
            return(false);
        }

        var u = Mathf.Abs(d01.x * d31.y - d01.y * d31.x) / denom; // close to v2
        var v = Mathf.Abs(d01.x * d21.y - d01.y * d21.x) / denom; // close to v3
        var w = 1 - u - v;                                        // close to v1

        // do lerp
        ret.vertex   = v2.vertex * u + v3.vertex * v + v1.vertex * w;
        ret.normal   = v2.normal * u + v3.normal * v + v1.normal * w;
        ret.worldPos = v2.worldPos * u + v3.worldPos * v + v1.worldPos * w;
        ret.uv       = v2.uv * u + v3.uv * v + v1.uv * w;
        ret.color    = v2.color * u + v3.color * v + v1.color * w;

        return(true);
    }
    void DoNDCCoord(FragmentIn frag)
    {
        var projectv = frag.vertex;

        // 转换到NDC空间,再到viewport空间
        projectv.x = (projectv.x / projectv.w / 2 + 0.5f) * width;
        projectv.y = (projectv.y / projectv.w / 2 + 0.5f) * height;
        projectv.z = (projectv.z / projectv.w + 0.5f);

        frag.vertex = projectv;

        frag.pixelx = (int)projectv.x;
        frag.pixely = (int)projectv.y;
    }
Exemple #3
0
    public Color Frag(FragmentIn v)
    {
        var     color = ShaderGlobal.Ambient;
        Vector3 dir;       // 光线的反方向
        float   intensity; //光线强度
        Vector3 viewdir = (ShaderGlobal.CameraPos - v.worldPos).normalized;

        foreach (var light in ShaderGlobal.lights)
        {
            switch (light.type)
            {
            // 这一部分计算要预处理下
            case LightType.Directional:
                dir       = -light.transform.forward;
                intensity = light.intensity;
                break;

            case LightType.Point:
                dir = light.transform.position - v.worldPos;
                // 正常的intensity公式是 1/(a+b*dis+c*dis^2)
                intensity = Mathf.Clamp01(light.intensity * (1 - dir.magnitude / light.range));

                dir.Normalize();
                break;

            case LightType.Spot:
                dir = light.transform.position - v.worldPos;
                float rho = Mathf.Max(0, Vector3.Dot(dir.normalized, -light.transform.forward));
                intensity = Mathf.Clamp01((Mathf.Cos(light.spotAngle * Mathf.Deg2Rad) - rho) * light.intensity * (1 - dir.magnitude / light.range));
                dir.Normalize();
                break;

            default:
                dir       = -light.transform.forward;
                intensity = light.intensity;
                break;
            }
            float   diff = Mathf.Max(0, Vector3.Dot(v.normal, dir));
            Vector3 h    = (dir + viewdir).normalized;
            float   nh   = Vector3.Dot(h, v.normal);
            float   spec = Mathf.Pow(nh, ShaderGlobal.Specular);

            color += (ShaderGlobal.Albedo * light.color * diff + ShaderGlobal.SpecularColor * light.color * spec) * intensity;
        }

        return(color);
        //return new Color(v.uv.x, v.uv.y, 0);
        //return new Color(v.normal.x, v.normal.y, v.normal.z, 1);
    }
Exemple #4
0
    public FragmentIn Vert(VertexIn v)
    {
        var vert = new FragmentIn();

        vert.worldPos = ShaderGlobal.l2wMat.MultiplyPoint3x4(v.pos);
        vert.normal   = ShaderGlobal.l2wInvTMat.MultiplyVector(v.normal).normalized;
        vert.uv       = v.uv;
        vert.color    = v.color;

        Vector4 pos = v.pos;

        pos.w       = 1;
        vert.vertex = ShaderGlobal.MVPMat * pos;

        return(vert);
    }
Exemple #5
0
    public List <FragmentIn> Rast(FragmentIn v1, FragmentIn v2, FragmentIn v3)
    {
        var p1 = v1.vertex;
        var p2 = v2.vertex;
        var p3 = v3.vertex;

        int xMin     = (int)Mathf.Min(p1.x, p2.x, p3.x);
        int xMax     = (int)Mathf.Max(p1.x, p2.x, p3.x);
        int yMin     = (int)Mathf.Min(p1.y, p2.y, p3.y);
        int yMax     = (int)Mathf.Max(p1.y, p2.y, p3.y);
        var fragList = new List <FragmentIn>((xMax - xMin) * (yMax - yMin));

        for (int m = xMin; m < xMax + 1; m++)
        {
            for (int n = yMin; n < yMax + 1; n++)
            {
                if (m < 0 || m > width - 1 || n < 0 || n > height - 1)
                {
                    continue;
                }
                if (!isLeftPoint(p1, p2, m + 0.5f, n + 0.5f))
                {
                    continue;
                }
                if (!isLeftPoint(p2, p3, m + 0.5f, n + 0.5f))
                {
                    continue;
                }
                if (!isLeftPoint(p3, p1, m + 0.5f, n + 0.5f))
                {
                    continue;
                }
                var frag = new FragmentIn();
                frag.pixelx = m;
                frag.pixely = n;
                LerpFragment(v1, v2, v3, frag);
                fragList.Add(frag);
            }
        }
        return(fragList);
    }
        Vector4 FS(FragmentIn input)
        {
            float r = Sample(Tex, TexSampler, input.TexCoord).X;

            return(new Vector4(r, r, r, r));
        }
 Vector4 FS(FragmentIn input)
 {
     return(Sample(Tex, TexSampler, input.TexCoord));
     //float r = Sample(Tex, TexSampler, input.TexCoord).X;
     //return new Vector4(r, r, r, r);
 }
Exemple #8
0
 Vector4 FS(FragmentIn input)
 {
     return(Sample(Tex, TexSampler, input.TexCoord));
 }