Где ошибка в шейдере мягких теней.

Для экспериментальных разработок и тем "я нашел чужой исходник, почему он не работает?"

Где ошибка в шейдере мягких теней.

Сообщение Fox Rex 26 окт 2010, 08:38

Код: Выделить всё
Shader "Shodow" {
   Properties {
   lightPosition ("Light Pos", Vector)=(0.0,0.0,0.0,0.0)
   lightRadius ("Light Radius", Float)=1.0
   lightRange ("Light Range", Float)=0.5
   zTexture ("Test",2D)="" {}   
   }
   SubShader {
         
      Pass
      {
      CGPROGRAM
      
      #pragma target 3.0
      #pragma vertex ExtrudePenumbra
      #pragma fragment PenumbraAlpha
      
      
      

      float4x4 invTransform; // invTransform = ~worldViewProjMatrix
      float4x4 worldViewMatrix;
      float4x4 worldViewProjMatrix;
      
      float4 lightPosition; //координаты источника света
      float  lightRadius; // радиус источника света
      float  lightRange;
      
      texture zTexture;
      sampler zTextureSampler = sampler_state
      {
          Texture   = (zTexture);
          MinFilter = LINEAR;
          MagFilter = LINEAR;
      };
      
      
      
      struct VS_INPUT_VE
      {
           float4 position    : POSITION;
           float3 vNormal0    : TEXCOORD0; // нормаль в первой вершине ребра
           float3 vNormal1    : TEXCOORD1; // нормаль во второй вершине ребра
           float4 normal      : NORMAL;     // нормаль к первой смежной грани ребра
           float3 backNormal  : TEXCOORD2; // нормаль ко второй смежной грани ребра
           float4 edge        : TEXCOORD3; // ребро соединяющее данную вершину ребра с другой
      };

      struct VS_OUTPUT_VE
      {
           float4 position    : POSITION;
           float4 front       : TEXCOORD0; // плоскости ограничивающие пенумбральный клин
           float4 back        : TEXCOORD1;
           float4 left        : TEXCOORD2;
           float4 right       : TEXCOORD3;    
           float4 projPos     : TEXCOORD4; // та же позиция, пригодится в пиксельном шейдере
      };
   
      // нахождение левой и правой плоскости пенумбрального клина
      float4 GetLRPlane(float3 pos, float3 sv0, float3 sv1)
      {
           float4 plane;
      
           plane.xyz = normalize( cross(pos - sv0, pos - sv1) );
           plane.w = -dot(pos, plane.xyz);   

           return plane;
      }

      // нахождение передней и задней плоскости пенумбрального клина
      float4 GetFBPlane(float3 pos, float3 edge, float3 sv)
      {
           float4 plane;
   
           plane.xyz = normalize( cross(edge, pos - sv) );
           plane.w = -dot(pos, plane.xyz);
   
           return plane;
      }

      // Вершинный шейдер, выполняющий построение пенумбрального клина
      VS_OUTPUT_VE ExtrudePenumbra( VS_INPUT_VE vertex )
      {
           VS_OUTPUT_VE    result;
           float4     extruded;
           float3   dir;
           float3     sphereVert0, sphereVert1;
   
           // Если обе грани ребра освещены, или неосвещены одновременно,
           // то данная вершина не входит в пенумбральный клин
           dir = vertex.position - lightPosition;
           if ( dot(dir, vertex.normal) * dot(dir, vertex.backNormal) > 0.0 )
          {
             result.front = result.back = result.left = result.right = 0.0;
             result.projPos = result.position = 0.0;
             return result;
          }

          // Мы немного увеличим пенумбру, чтобы не было прорези
          // между тенью и полутенью
          sphereVert0 = lightPosition + vertex.vNormal0 * 0.15;
          sphereVert1 = lightPosition - vertex.vNormal0 * lightRadius;
          extruded = vertex.position;   
          if ( vertex.normal.w > 0.0 ) // в w-компоненте указано как вытягивать вершину
          {
               // вытягивание от источника, вершина лежит в back-плоскости клина
               dir = vertex.position.xyz - sphereVert0;
               extruded.xyz += normalize(dir) * (lightRange - length(dir));
          }
          else if ( vertex.normal.w < 0.0 )
          {
               // вершина лежит в front-плоскости клина
               dir = vertex.position.xyz - sphereVert1;   
               extruded.xyz += normalize(dir) * (lightRange - length(dir));
          }      
          // Еслм w == 0 не вытягиваем вершину
          result.projPos = result.position = mul(extruded, worldViewProjMatrix);
      
          // w - хранит ориентацию ребра. Если ребро идёт от первой вершины
          // до второй, то w == 1.0, иначе -1.0.
          // Необходимо "развернуть" ребро во второй вершине,
          // чтобы нормали к front, back плоскостям не поменяли знак
          dir = vertex.edge * vertex.edge.w;
          // Находим плоскости пенумбрального клина
          result.front = GetFBPlane(vertex.position.xyz, dir, sphereVert1);
          result.back = -GetFBPlane(vertex.position.xyz, dir, sphereVert0);

          // во второй вершине left и right плоскости меняются местами
          if (vertex.edge.w > 0.0)
          {
               result.left = -GetLRPlane(vertex.position.xyz, sphereVert0, sphereVert1);
               result.right = GetLRPlane(vertex.position.xyz + vertex.edge.xyz, lightPosition,
                                             sphereVert0 - vertex.vNormal1 * lightRadius);
          }
          else
          {
               result.right = -GetLRPlane(vertex.position.xyz, sphereVert0, sphereVert1);
               result.left = GetLRPlane(vertex.position.xyz + vertex.edge.xyz, lightPosition,
                                                sphereVert0 - vertex.vNormal1 * lightRadius);
          }
   
          return result;   
        }   

      // Пиксельный шейдер, рассчитывающий освещённость в точке.
      // Работаем в системе координат объекта
      float4 PenumbraAlpha( VS_OUTPUT_VE vertex ) : COLOR0
      {
           // Надо найти текстурную координату, соответствующую точке сцены
           float2 projPos = vertex.projPos / vertex.projPos.w;
           float2 texel = float2(projPos.x + 1.0, -projPos.y + 1.0) / 2.0;
      
           // Кордината точки в сцене
           float4 vertPos = mul(float4(projPos.x, projPos.y, tex2D(zTextureSampler, texel).r, 1.0), invTransform);

           // Расстояния до внутренней и внешней плоскости клина
           float  distInner = dot(vertPos, vertex.back);
           float  distOuter = dot(vertPos, vertex.front);

           // Смотрим, чтобы мы находились внутри пенумбрального клина
           if (dot(vertPos, vertex.left) * dot(vertPos, vertex.right) > 0.0 && distInner * distOuter > 0.0)
           {
             float alpha = distInner / (distOuter + distInner);
             // Для сферического источника освещённость в пенумбральном клине
             // изменяется не линейно, это небольшое улучшение
             return 3*pow(alpha, 2.0) - 2*pow(alpha, 3.0);
          }
          else
             return 1.0;
        }
      ENDCG
      }
   }
   FallBack "Diffuse"
}

Шейдер не доделан. Если его использовать теней не будет. Выложу когда закончу.
Never more!
Аватара пользователя
Fox Rex
UNITрон
 
Сообщения: 218
Зарегистрирован: 04 сен 2010, 11:24

Re: Где ошибка в шейдере мягких теней.

Сообщение Fox Rex 26 окт 2010, 10:20

Вопрос снят.
Never more!
Аватара пользователя
Fox Rex
UNITрон
 
Сообщения: 218
Зарегистрирован: 04 сен 2010, 11:24

Re: Где ошибка в шейдере мягких теней.

Сообщение gnoblin 26 окт 2010, 11:45

Получилось? )
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Где ошибка в шейдере мягких теней.

Сообщение Fox Rex 26 окт 2010, 15:56

Нет, нужен рендер в текстуру, т.е. про версия. Хотя если есть способ получить значение буфера глубины в фрагментарном шейдере, то все может получиться.
Never more!
Аватара пользователя
Fox Rex
UNITрон
 
Сообщения: 218
Зарегистрирован: 04 сен 2010, 11:24

Re: Где ошибка в шейдере мягких теней.

Сообщение gnoblin 26 окт 2010, 16:35

А для чего рендер в текстуру?
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Где ошибка в шейдере мягких теней.

Сообщение antonio 26 окт 2010, 17:09

Такой подойдет?

Синтаксис:
Используется glsl
Shader "Render Depth" {
        SubShader {
                Tags { "RenderType"="Opaque" }
                Pass {
                        Fog { Mode Off }
                        CGPROGRAM
                        #pragma vertex vert
                        #pragma fragment frag
                        #include "UnityCG.cginc"

                        struct v2f {
                                float4 pos : POSITION;
                                float2 depth : TEXCOORD0;
                        };

                        v2f vert( appdata_base v ) {
                                v2f o;
                                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                                UNITY_TRANSFER_DEPTH(o.depth);
                                return o;
                        }

                        half4 frag(v2f i) : COLOR {
                                UNITY_OUTPUT_DEPTH(i.depth);
                        }
                        ENDCG
                }
        }
}
 
Аватара пользователя
antonio
UNIт
 
Сообщения: 132
Зарегистрирован: 03 ноя 2009, 15:42
Откуда: Смоленск

Re: Где ошибка в шейдере мягких теней.

Сообщение Fox Rex 26 окт 2010, 23:46

Рендер в текстуру, нужен для того чтобы через шейдер записать в текстуру значения глубины.
antonio, предложный вариант получения глубины годиться только для про так как рендерить его нужно в текстуру.
http://www.uraldev.ru/articles/id/18 вот исходники и статья по мягким теням, тени получаются весьма привлекательные, только вопрос в производительности. Те у кого про могут реализовать этот вариант.
Never more!
Аватара пользователя
Fox Rex
UNITрон
 
Сообщения: 218
Зарегистрирован: 04 сен 2010, 11:24

Re: Где ошибка в шейдере мягких теней.

Сообщение gnoblin 27 окт 2010, 02:02

Ты можешь поставить триалку и реализовать этот вариант).

А если попробовать без ртт, но в два пасса как-нибудь?

Рисуешь в первом пассе глубину, потом grabpass как мне тут показывали в одной из тем, потом уже второй пасс с использованием _GrabPass с инфой про глубину?
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Где ошибка в шейдере мягких теней.

Сообщение Fox Rex 27 окт 2010, 07:08

Вопрос в том выводиться ли на экран, то что захватывает GrabPass, если нет, то можно тени во фри сделать. Попробую проверить. Но тогда надо найти ошибку в приведенном коде, я так ее и не нашел.
Never more!
Аватара пользователя
Fox Rex
UNITрон
 
Сообщения: 218
Зарегистрирован: 04 сен 2010, 11:24

Re: Где ошибка в шейдере мягких теней.

Сообщение Fox Rex 27 окт 2010, 07:24

Код: Выделить всё
Shader "Shodow" {

   Properties {

   lightPosition ("Light Pos", Vector)=(0.0,0.0,0.0,0.0)

   lightRadius ("Light Radius", Float)=1.0

   lightRange ("Light Range", Float)=0.5

     

   }

   SubShader {

         

      UsePass "Diffuse"

      Pass

      {

         CGPROGRAM

     

         #pragma target 3.0

         #pragma vertex ZFillVS

         #pragma fragment ZFillPS

         float4x4 worldViewProjMatrix;

         struct VS_OUTPUT_ZF

      {

         float4    position      : POSITION;

          float4  depth         : TEXCOORD0; // in word space

      };

         

         VS_OUTPUT_ZF ZFillVS( float4 position : POSITION )

      {

         VS_OUTPUT_ZF    result;

   

         result.position = mul(position, worldViewProjMatrix);

         result.depth   = result.position;//result.position.z/result.position.w;

   

         return result;

      }

      

      float4 ZFillPS( VS_OUTPUT_ZF vertex ) : COLOR0

      {

         return float4(vertex.depth.z/vertex.depth.w, 0.0f, 0.0f, 1.0f);

      }

        ENDCG

      }

      GrabPass { }

      Pass

      {

      CGPROGRAM

     

      #pragma target 3.0

      #pragma vertex ExtrudePenumbra

      #pragma fragment PenumbraAlpha

     

     

     



      float4x4 invTransform; // invTransform = ~worldViewProjMatrix

      float4x4 worldViewMatrix;

      float4x4 worldViewProjMatrix;

     

      float4 lightPosition; //координаты источника света

      float  lightRadius; // радиус источника света

      float  lightRange;

     

     

      sampler zTextureSampler = sampler_state

      {

          Texture   = (_GrabTexture);

          MinFilter = LINEAR;

          MagFilter = LINEAR;

      };

     

     

     

      struct VS_INPUT_VE

      {

           float4 position    : POSITION;

           float3 vNormal0    : TEXCOORD0; // нормаль в первой вершине ребра

           float3 vNormal1    : TEXCOORD1; // нормаль во второй вершине ребра

           float4 normal      : NORMAL;     // нормаль к первой смежной грани ребра

           float3 backNormal  : TEXCOORD2; // нормаль ко второй смежной грани ребра

           float4 edge        : TEXCOORD3; // ребро соединяющее данную вершину ребра с другой

      };



      struct VS_OUTPUT_VE

      {

           float4 position    : POSITION;

           float4 front       : TEXCOORD0; // плоскости ограничивающие пенумбральный клин

           float4 back        : TEXCOORD1;

           float4 left        : TEXCOORD2;

           float4 right       : TEXCOORD3;   

           float4 projPos     : TEXCOORD4; // та же позиция, пригодится в пиксельном шейдере

      };

   

      // нахождение левой и правой плоскости пенумбрального клина

      float4 GetLRPlane(float3 pos, float3 sv0, float3 sv1)

      {

           float4 plane;

     

           plane.xyz = normalize( cross(pos - sv0, pos - sv1) );

           plane.w = -dot(pos, plane.xyz);   



           return plane;

      }



      // нахождение передней и задней плоскости пенумбрального клина

      float4 GetFBPlane(float3 pos, float3 edge, float3 sv)

      {

           float4 plane;

   

           plane.xyz = normalize( cross(edge, pos - sv) );

           plane.w = -dot(pos, plane.xyz);

   

           return plane;

      }



      // Вершинный шейдер, выполняющий построение пенумбрального клина

      VS_OUTPUT_VE ExtrudePenumbra( VS_INPUT_VE vertex )

      {

           VS_OUTPUT_VE    result;

           float4     extruded;

           float3   dir;

           float3     sphereVert0, sphereVert1;

   

           // Если обе грани ребра освещены, или неосвещены одновременно,

           // то данная вершина не входит в пенумбральный клин

           dir = vertex.position - lightPosition;

           if ( dot(dir, vertex.normal) * dot(dir, vertex.backNormal) > 0.0 )

          {

             result.front = result.back = result.left = result.right = 0.0;

             result.projPos = result.position = 0.0;

             return result;

          }



          // Мы немного увеличим пенумбру, чтобы не было прорези

          // между тенью и полутенью

          sphereVert0 = lightPosition + vertex.vNormal0 * 0.15;

          sphereVert1 = lightPosition - vertex.vNormal0 * lightRadius;

          extruded = vertex.position;   

          if ( vertex.normal.w > 0.0 ) // в w-компоненте указано как вытягивать вершину

          {

               // вытягивание от источника, вершина лежит в back-плоскости клина

               dir = vertex.position.xyz - sphereVert0;

               extruded.xyz += normalize(dir) * (lightRange - length(dir));

          }

          else if ( vertex.normal.w < 0.0 )

          {

               // вершина лежит в front-плоскости клина

               dir = vertex.position.xyz - sphereVert1;   

               extruded.xyz += normalize(dir) * (lightRange - length(dir));

          }     

          // Еслм w == 0 не вытягиваем вершину

          result.projPos = result.position = mul(extruded, worldViewProjMatrix);

     

          // w - хранит ориентацию ребра. Если ребро идёт от первой вершины

          // до второй, то w == 1.0, иначе -1.0.

          // Необходимо "развернуть" ребро во второй вершине,

          // чтобы нормали к front, back плоскостям не поменяли знак

          dir = vertex.edge * vertex.edge.w;

          // Находим плоскости пенумбрального клина

          result.front = GetFBPlane(vertex.position.xyz, dir, sphereVert1);

          result.back = -GetFBPlane(vertex.position.xyz, dir, sphereVert0);



          // во второй вершине left и right плоскости меняются местами

          if (vertex.edge.w > 0.0)

          {

               result.left = -GetLRPlane(vertex.position.xyz, sphereVert0, sphereVert1);

               result.right = GetLRPlane(vertex.position.xyz + vertex.edge.xyz, lightPosition,

                                             sphereVert0 - vertex.vNormal1 * lightRadius);

          }

          else

          {

               result.right = -GetLRPlane(vertex.position.xyz, sphereVert0, sphereVert1);

               result.left = GetLRPlane(vertex.position.xyz + vertex.edge.xyz, lightPosition,

                                                sphereVert0 - vertex.vNormal1 * lightRadius);

          }

   

          return result;   

        }   



      // Пиксельный шейдер, рассчитывающий освещённость в точке.

      // Работаем в системе координат объекта

      float4 PenumbraAlpha( VS_OUTPUT_VE vertex ) : COLOR0

      {

           // Надо найти текстурную координату, соответствующую точке сцены

           float2 projPos = vertex.projPos / vertex.projPos.w;

           float2 texel = float2(projPos.x + 1.0, -projPos.y + 1.0) / 2.0;

     

           // Кордината точки в сцене

           float4 vertPos = mul(float4(projPos.x, projPos.y, tex2D(zTextureSampler, texel).r, 1.0), invTransform);



           // Расстояния до внутренней и внешней плоскости клина

           float  distInner = dot(vertPos, vertex.back);

           float  distOuter = dot(vertPos, vertex.front);



           // Смотрим, чтобы мы находились внутри пенумбрального клина

           if (dot(vertPos, vertex.left) * dot(vertPos, vertex.right) > 0.0 && distInner * distOuter > 0.0)

           {

             float alpha = distInner / (distOuter + distInner);

             // Для сферического источника освещённость в пенумбральном клине

             // изменяется не линейно, это небольшое улучшение

             return 3*pow(alpha, 2.0) - 2*pow(alpha, 3.0);

          }

          else

             return 1.0;

        }

      ENDCG

      }

   }

   FallBack "Diffuse"

}

Вот весь шейдер. Остается вопрос по ошибкам, не могу найти.
Never more!
Аватара пользователя
Fox Rex
UNITрон
 
Сообщения: 218
Зарегистрирован: 04 сен 2010, 11:24

Re: Где ошибка в шейдере мягких теней.

Сообщение Fox Rex 27 окт 2010, 10:46

В чем ошибка разобрался. Но теперь другая напасть. Юнити не дает доступ ко всем входным данным?
Код: Выделить всё
Shader "Shodow" {

   Properties {

   lightPosition ("Light Pos", Vector)=(0.0,0.0,0.0,0.0)

   lightRadius ("Light Radius", Float)=1.0

   lightRange ("Light Range", Float)=0.5

     

   }

   SubShader {

         

      UsePass "Diffuse"

      Pass

      {

         CGPROGRAM

     

         #pragma target 3.0

         #pragma vertex ZFillVS

         #pragma fragment ZFillPS

         float4x4 worldViewProjMatrix;

         struct VS_OUTPUT_ZF

      {

         float4    position      : POSITION;

          float4  depth         : TEXCOORD0; // in word space

      };

         

         VS_OUTPUT_ZF ZFillVS( float4 position : POSITION )

      {

         VS_OUTPUT_ZF    result;

   

         result.position = mul(position, worldViewProjMatrix);

         result.depth   = result.position;//result.position.z/result.position.w;

   

         return result;

      }

      

      float4 ZFillPS( VS_OUTPUT_ZF vertex ) : COLOR0

      {

         return float4(vertex.depth.z/vertex.depth.w, 0.0f, 0.0f, 1.0f);

      }

        ENDCG

      }

      GrabPass { }

      Pass

      {

         

      CGPROGRAM

     

      #pragma target 3.0

      #pragma vertex ExtrudePenumbra

      #pragma fragment PenumbraAlpha

     

     

     



      float4x4 invTransform; // invTransform = ~worldViewProjMatrix

      float4x4 worldViewMatrix;

      float4x4 worldViewProjMatrix;

     

      float4 lightPosition; //координаты источника света

      float  lightRadius; // радиус источника света

      float  lightRange;

     

     

      sampler zTextureSampler = sampler_state

      {

          Texture   = (_GrabTexture);

          MinFilter = LINEAR;

          MagFilter = LINEAR;

      };

     

     

     

      struct VS_INPUT_VE

   {

        float4 vertex;

        float3 texcoord0;    // нормаль в первой вершине ребра

        float3 texcoord1;     // нормаль во второй вершине ребра

        float4 normal;          // нормаль к первой смежной грани ребра

        float3 texcoord2;   // нормаль ко второй смежной грани ребра

        float4 texcoord3 ;        // ребро соединяющее данную вершину ребра с другой

   };



      struct VS_OUTPUT_VE

      {

           float4 pos         : POSITION;

           float4 fr          : TEXCOORD0; // плоскости ограничивающие пенумбральный клин

           float4 bk          : TEXCOORD1;

           float4 left        : TEXCOORD2;

           float4 right       : TEXCOORD3;   

           float4 projPos     : TEXCOORD4; // та же позиция, пригодится в пиксельном шейдере

      };

   

      // нахождение левой и правой плоскости пенумбрального клина

      float4 GetLRPlane(float3 pos, float3 sv0, float3 sv1)

      {

           float4 plane;

     

           plane.xyz = normalize( cross(pos - sv0, pos - sv1) );

           plane.w = -dot(pos, plane.xyz);   



           return plane;

      }



      // нахождение передней и задней плоскости пенумбрального клина

      float4 GetFBPlane(float3 pos, float3 edge, float3 sv)

      {

           float4 plane;

   

           plane.xyz = normalize( cross(edge, pos - sv) );

           plane.w = -dot(pos, plane.xyz);

   

           return plane;

      }



      // Вершинный шейдер, выполняющий построение пенумбрального клина

      VS_OUTPUT_VE ExtrudePenumbra( VS_INPUT_VE ver )

      {

           VS_OUTPUT_VE    result;

           float4     extruded;

           float3   dir;

           float3     sphereVert0, sphereVert1;

   

           // Если обе грани ребра освещены, или неосвещены одновременно,

           // то данная вершина не входит в пенумбральный клин

           dir = ver.vertex - lightPosition;

           if ( dot(dir, ver.normal) * dot(dir, ver.texcoord2) > 0.0 )

          {

             result.fr = result.bk = result.left = result.right = 0.0;

             result.projPos = result.pos = 0.0;

             return result;

          }



          // Мы немного увеличим пенумбру, чтобы не было прорези

          // между тенью и полутенью

          sphereVert0 = lightPosition + ver.texcoord0 * 0.15;

          sphereVert1 = lightPosition - ver.texcoord0 * lightRadius;

          extruded = ver.vertex;   

          if ( ver.normal.w > 0.0 ) // в w-компоненте указано как вытягивать вершину

          {

               // вытягивание от источника, вершина лежит в back-плоскости клина

               dir = ver.vertex.xyz - sphereVert0;

               extruded.xyz += normalize(dir) * (lightRange - length(dir));

          }

          else if ( ver.normal.w < 0.0 )

          {

               // вершина лежит в front-плоскости клина

               dir = ver.vertex.xyz - sphereVert1;   

               extruded.xyz += normalize(dir) * (lightRange - length(dir));

          }     

          // Еслм w == 0 не вытягиваем вершину

          result.projPos = result.pos = mul(extruded, worldViewProjMatrix);

     

          // w - хранит ориентацию ребра. Если ребро идёт от первой вершины

          // до второй, то w == 1.0, иначе -1.0.

          // Необходимо "развернуть" ребро во второй вершине,

          // чтобы нормали к front, back плоскостям не поменяли знак

          dir = ver.texcoord3 * ver.texcoord3.w;

          // Находим плоскости пенумбрального клина

          result.fr = GetFBPlane(ver.vertex.xyz, dir, sphereVert1);

          result.bk = -GetFBPlane(ver.vertex.xyz, dir, sphereVert0);



          // во второй вершине left и right плоскости меняются местами

          if (ver.texcoord3.w > 0.0)

          {

               result.left = -GetLRPlane(ver.vertex.xyz, sphereVert0, sphereVert1);

               result.right = GetLRPlane(ver.vertex.xyz + ver.texcoord3.xyz, lightPosition,

                                             sphereVert0 - ver.texcoord1 * lightRadius);

          }

          else

          {

               result.right = -GetLRPlane(ver.vertex.xyz, sphereVert0, sphereVert1);

               result.left = GetLRPlane(ver.vertex.xyz + ver.texcoord3.xyz, lightPosition,

                                                sphereVert0 - ver.texcoord1 * lightRadius);

          }

   

          return result;   

        }   



      // Пиксельный шейдер, рассчитывающий освещённость в точке.

      // Работаем в системе координат объекта

      float4 PenumbraAlpha( VS_OUTPUT_VE ver ) : COLOR0

      {

           // Надо найти текстурную координату, соответствующую точке сцены

           float2 projPos = ver.projPos / ver.projPos.w;

           float2 texel = float2(projPos.x + 1.0, -projPos.y + 1.0) / 2.0;

     

           // Кордината точки в сцене

           float4 vertPos = mul(float4(projPos.x, projPos.y, tex2D(zTextureSampler, texel).r, 1.0), invTransform);



           // Расстояния до внутренней и внешней плоскости клина

           float  distInner = dot(vertPos, ver.bk);

           float  distOuter = dot(vertPos, ver.fr);



           // Смотрим, чтобы мы находились внутри пенумбрального клина

           if (dot(vertPos, ver.left) * dot(vertPos, ver.right) > 0.0 && distInner * distOuter > 0.0)

           {

             float alpha = distInner / (distOuter + distInner);

             // Для сферического источника освещённость в пенумбральном клине

             // изменяется не линейно, это небольшое улучшение

             return 3*pow(alpha, 2.0) - 2*pow(alpha, 3.0);

          }

          else

             return 1.0;

        }

      ENDCG

      }

   }

   FallBack "Diffuse"

}
Never more!
Аватара пользователя
Fox Rex
UNITрон
 
Сообщения: 218
Зарегистрирован: 04 сен 2010, 11:24

Re: Где ошибка в шейдере мягких теней.

Сообщение Neodrop 27 окт 2010, 14:00

Вы когда-нибудь научитесь пользоваться тегом syntax :-w ?
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Где ошибка в шейдере мягких теней.

Сообщение Fox Rex 27 окт 2010, 15:30

Не тот вариант в предыдущем посте вставил.
Синтаксис:
Используется glsl
Shader "Shodow" {

   Properties {

   lightPosition ("Light Pos", Vector)=(0.0,0.0,0.0,0.0)

   lightRadius ("Light Radius", Float)=1.0

   lightRange ("Light Range", Float)=0.5

     

   }

   SubShader {

         

      UsePass "Diffuse"

      Pass

      {

        CGPROGRAM

     

        #pragma target 3.0

        #pragma vertex ZFillVS

        #pragma fragment ZFillPS

        float4x4 worldViewProjMatrix;

        struct VS_OUTPUT_ZF

                {

                        float4  position                : POSITION;

                float4  depth                   : TEXCOORD0; // in word space

                };

       

        VS_OUTPUT_ZF ZFillVS( float4 position : POSITION )

                {

                        VS_OUTPUT_ZF    result;

       

                        result.position = mul(position, worldViewProjMatrix);

                        result.depth    = result.position;//result.position.z/result.position.w;

       

                        return result;

                }

               

                float4 ZFillPS( VS_OUTPUT_ZF vertex ) : COLOR0

                {

                        return float4(vertex.depth.z/vertex.depth.w, 0.0f, 0.0f, 1.0f);

                }

        ENDCG

      }

      GrabPass { }

      Pass

      {

       

      CGPROGRAM

     

      #pragma target 3.0

      #pragma vertex ExtrudePenumbra

      #pragma fragment PenumbraAlpha

     

     

     



      float4x4 invTransform; // invTransform = ~worldViewProjMatrix

      float4x4 worldViewMatrix;

      float4x4 worldViewProjMatrix;

     

      float4 lightPosition; //координаты источника света

      float  lightRadius; // радиус источника света

      float  lightRange;

     

     

      sampler zTextureSampler = sampler_state

      {

          Texture   = (_GrabTexture);

          MinFilter = LINEAR;

          MagFilter = LINEAR;

      };

     

     

     

      struct VS_INPUT_VE

        {

                float4 vertex;

                float3 texcoord0;    // нормаль в первой вершине ребра

                float3 texcoord1;     // нормаль во второй вершине ребра

                float4 normal;          // нормаль к первой смежной грани ребра

                float3 texcoord2;   // нормаль ко второй смежной грани ребра

                float4 texcoord3 ;        // ребро соединяющее данную вершину ребра с другой

        };



      struct VS_OUTPUT_VE

      {

           float4 pos         : POSITION;

           float4 fr          : TEXCOORD0; // плоскости ограничивающие пенумбральный клин

           float4 bk          : TEXCOORD1;

           float4 left        : TEXCOORD2;

           float4 right       : TEXCOORD3;    

           float4 projPos     : TEXCOORD4; // та же позиция, пригодится в пиксельном шейдере

      };

   

      // нахождение левой и правой плоскости пенумбрального клина

      float4 GetLRPlane(float3 pos, float3 sv0, float3 sv1)

      {

           float4 plane;

     

           plane.xyz = normalize( cross(pos - sv0, pos - sv1) );

           plane.w = -dot(pos, plane.xyz);  



           return plane;

      }



      // нахождение передней и задней плоскости пенумбрального клина

      float4 GetFBPlane(float3 pos, float3 edge, float3 sv)

      {

           float4 plane;

   

           plane.xyz = normalize( cross(edge, pos - sv) );

           plane.w = -dot(pos, plane.xyz);

   

           return plane;

      }



      // Вершинный шейдер, выполняющий построение пенумбрального клина

      VS_OUTPUT_VE ExtrudePenumbra( VS_INPUT_VE ver )

      {

           VS_OUTPUT_VE    result;

           float4     extruded;

           float3   dir;

           float3     sphereVert0, sphereVert1;

   

           // Если обе грани ребра освещены, или неосвещены одновременно,

           // то данная вершина не входит в пенумбральный клин

           dir = ver.vertex - lightPosition;

           if ( dot(dir, ver.normal) * dot(dir, ver.texcoord2) > 0.0 )

          {

             result.fr = result.bk = result.left = result.right = 0.0;

             result.projPos = result.pos = 0.0;

             return result;

          }



          // Мы немного увеличим пенумбру, чтобы не было прорези

          // между тенью и полутенью

          sphereVert0 = lightPosition + ver.texcoord0 * 0.15;

          sphereVert1 = lightPosition - ver.texcoord0 * lightRadius;

          extruded = ver.vertex;  

          if ( ver.normal.w > 0.0 ) // в w-компоненте указано как вытягивать вершину

          {

               // вытягивание от источника, вершина лежит в back-плоскости клина

               dir = ver.vertex.xyz - sphereVert0;

               extruded.xyz += normalize(dir) * (lightRange - length(dir));

          }

          else if ( ver.normal.w < 0.0 )

          {

               // вершина лежит в front-плоскости клина

               dir = ver.vertex.xyz - sphereVert1;  

               extruded.xyz += normalize(dir) * (lightRange - length(dir));

          }      

          // Еслм w == 0 не вытягиваем вершину

          result.projPos = result.pos = mul(extruded, worldViewProjMatrix);

     

          // w - хранит ориентацию ребра. Если ребро идёт от первой вершины

          // до второй, то w == 1.0, иначе -1.0.

          // Необходимо "развернуть" ребро во второй вершине,

          // чтобы нормали к front, back плоскостям не поменяли знак

          dir = ver.texcoord3 * ver.texcoord3.w;

          // Находим плоскости пенумбрального клина

          result.fr = GetFBPlane(ver.vertex.xyz, dir, sphereVert1);

          result.bk = -GetFBPlane(ver.vertex.xyz, dir, sphereVert0);



          // во второй вершине left и right плоскости меняются местами

          if (ver.texcoord3.w > 0.0)

          {

               result.left = -GetLRPlane(ver.vertex.xyz, sphereVert0, sphereVert1);

               result.right = GetLRPlane(ver.vertex.xyz + ver.texcoord3.xyz, lightPosition,

                                             sphereVert0 - ver.texcoord1 * lightRadius);

          }

          else

          {

               result.right = -GetLRPlane(ver.vertex.xyz, sphereVert0, sphereVert1);

               result.left = GetLRPlane(ver.vertex.xyz + ver.texcoord3.xyz, lightPosition,

                                                sphereVert0 - ver.texcoord1 * lightRadius);

          }

   

          return result;    

        }  



      // Пиксельный шейдер, рассчитывающий освещённость в точке.

      // Работаем в системе координат объекта

      float4 PenumbraAlpha( VS_OUTPUT_VE ver ) : COLOR0

      {

           // Надо найти текстурную координату, соответствующую точке сцены

           float2 projPos = ver.projPos / ver.projPos.w;

           float2 texel = float2(projPos.x + 1.0, -projPos.y + 1.0) / 2.0;

     

           // Кордината точки в сцене

           float4 vertPos = mul(float4(projPos.x, projPos.y, tex2D(zTextureSampler, texel).r, 1.0), invTransform);



           // Расстояния до внутренней и внешней плоскости клина

           float  distInner = dot(vertPos, ver.bk);

           float  distOuter = dot(vertPos, ver.fr);



           // Смотрим, чтобы мы находились внутри пенумбрального клина

           if (dot(vertPos, ver.left) * dot(vertPos, ver.right) > 0.0 && distInner * distOuter > 0.0)

           {

             float alpha = distInner / (distOuter + distInner);

             // Для сферического источника освещённость в пенумбральном клине

             // изменяется не линейно, это небольшое улучшение

             return 3*pow(alpha, 2.0) - 2*pow(alpha, 3.0);

          }

          else

             return 1.0;

        }

      ENDCG

      }

   }

   FallBack "Diffuse"

}
Последний раз редактировалось Fox Rex 27 окт 2010, 15:32, всего редактировалось 1 раз.
Never more!
Аватара пользователя
Fox Rex
UNITрон
 
Сообщения: 218
Зарегистрирован: 04 сен 2010, 11:24

Re: Где ошибка в шейдере мягких теней.

Сообщение Neodrop 27 окт 2010, 15:31

Почти получилось. Только пишем : syntax=glsl
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Где ошибка в шейдере мягких теней.

Сообщение gnoblin 27 окт 2010, 15:53

Какие "все" входные данные?

Вместо float4x4 invTransform; float4x4 worldViewMatrix; float4x4 worldViewProjMatrix; нужно использовать юнитевские матрицы из справки (popcorn1)
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

След.

Вернуться в Шейдерная кузня

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1