Mariya Mariya

Dreaman, Спасибо! =)

Dreaman Dreaman

Mariya, законченный вариант реально классно выглядит! Молодец :)

Mariya Mariya

Всем привет!
Сегодня хочу показать законченный вариант домика Сырны.

alexprey alexprey

StarPlosion: Битва с пиратами за планету

Wings' might Wings' might

Всем привет)
Добавил на этой неделе начальное окно, новую валюту и достижения:

alexprey alexprey

shadeborn, может быть они нашли способ как обойти полноценный запуск этих сервисов при запуске игры? Если так, то почему бы и не использовать единый клиент?) В любом случае, чем дальше все идет, там это все больше становится похоже на эту шутку

...
shadeborn shadeborn

Это всё круто, но...зачем? Ок есть Стим. Хорошо, теперь еще и ЕГС есть. Благо, комп не зашкварен Оригином...но у людей и он стоит. И для работы игр внутри этих сервисов нужны, собсно, эти сервисы. Так поверх этих сервисов нужно накатить еще один...

Devion Devion

согласен, есть кейсы которые без них вообще не делаются, не знать или избегать их определенно неправильно

Так точно, либо любое изменение в объекте на стороне редактора.

alexprey alexprey

Devion, только рад за дополнение, Спасибо)

хм, а вот это интересно, не пробовал никогда такой кейс.

Devion Devion

лёш, ты же не против если я дополню? )

скриптаблы, для понимания могут храниться на уровне ассета и на уровне сцены.

Mariya Mariya

Всем привет!
Начали работу над мебелью в домик Сырны, и первым сделали чайный столик с чайным сервизом. А так же продолжаем работу над анимациями.

Wings' might Wings' might

Всем привет)
За неделю в игру было добавлено меню настроек, переделана старая локация, добавлены новые враги и повышена производительности

alexprey alexprey

А мне кажется это такой особый хитрый ход, хотя с другой стороны как разработчики успеют к этому подготовиться получше 🤔

Dreaman Dreaman

Всем привет!
Для проекта "Mental State" разработано новое устройство, которое уже полностью функционирует внутри игрового мира. Оно носит название "Репульсивер". Совместно с очередными большими воротами это устройство образует новую головоломку...

...
Mariya Mariya

Всем привет!
На этой неделе мы научили Сырну летать!

Tartal Tartal

alexprey, кастомизации - создание внешности персонажа? Я всегда любил это, но не думаю, что это будет к месту в мясном шутере)
EfimovMax, да, есть немного)

Tartal Tartal

Jusper, точно не помню, уже как полгода точно) Я вроде в Дискорде немного обсуждал эту тему. Пока немножко попробовал движок - мне очень нравится. Ну, в конце концов, он идеально подходит под жанры, с которыми я хочу работать...

alexprey alexprey

Первая тема крутая очень!

Логотип проекта Unity

#3 Vertex and Fragment Shader

Vertex and Fragment Shader

В этой статье мы напишем простой вертексно-пиксельный шейдер, который
будет натягивать текстуру(логотип XGM) на объект(в моем случае на
сферу).
Итак, приступим.
Для начала создадим папку, где будем хранить шейдеры. Назовем ее
Shaders. Далее создадим шейдер: правый клик по папке
Shaders>Create>Shader>Unlit Shader. Назовем шейдер xgmSkin.

#3 Vertex and Fragment Shader — Unity — DevTribe: Разработка игр

Перед нами открылось окно редактора с содержанием стандартного Unlit
Shader'а. Выделяем все и смело удаляем. Начнем, как говориться, "с чистого листа".
Из предыдущей статьи мы уяснили, что в Unity шейдер пишется внутри
SubShader'а. Так-что давайте сначала напишем "фундамент".

Shader "MyShaders/xgmSkin" // путь и имя шейдера в выпадающем окне 
материала
{
  Properties // отображаемые в инспекторе свойства
   { 
    
   }
   SubShader 
   {
     Pass 
      {
        CGPROGRAM
        // тут будет CG код
        CGEND
      }
   }
  Fallback "Diffuse" 
}

Начнем заполнять блок Properties. В нем мы обозначаем внешние
переменные, которые будут видны в окне материала в инспекторе. Здесь нам
многого не нужно, только текстурка. Пишем:

  Properties 
  {
    _xgmTex("Texture",2D) = "white" {} 
  }

Ну и всё, никаких тэгов писать не будем, нам подходят настройки по
дефолту, так что сразу спускаемся в блок CGPROGRAM.
В статье по теории я писал, что мы можем назначать, какие данные примет и
вернет шейдер при помощи семантики. Для удобства записи в CG программе
эти данные объединяют в структуры. Давайте опишем входящую(vertexInput) и
выходящую(vertexOutput) структуры для вертексного шейдера:

struct vertexInput // входящие данные
      {
        float4 vertex:POSITION; // позиция вершины в пространстве модели
        float2 uv:TEXCOORD0; // uv координаты данной вершины 
  
      };
      struct vertexOutput // выходящие данные
      {
       float4 position:SV_POSITION; // позиция 
       float2 uv:TEXCOORD0; // uv координаты
      };
После структур обязательно ставится знак ";"

Данные описаны, теперь самое время писать векртексный шейдер. Ой, чуть не забыл)
Для того, что бы обозначить функцию как вертексный или пиксельный
шейдер, мы должны назначить имена для этих функций в директиве #pragma.

#pragma vertex vert 
#pragma fragmet frag 

А вот собственно сам вертексный шейдер:

vertexOutput vert(vertexInput v) 
      {
        vertexOutput o; // создаем возвращаемую структуру 
        o.position = mul(UNITY_MATRIX_MVP,poss); // переводим координатыиз пространства модели в проекционное 
        o.uv = v.uv; // просто передаем uv координаты
        return o; 
      }

Пиксельный шейдер возвращает только цвет, так что нужды создавать
отдельную структуру для него у нас нет. Поэтому,назначаем семантику
прямо для самого возвращаемого значения функции frag(Семантика для цвета
COLOR или SV_Target ). Так же нам нужно вытащить текстуру из
Properties.Напомню, что имя внешней переменной должно быть такое-же, как в
Properties, что бы движок сам передал ей значение.

      uniform sampler2D _xgmTex; // внешняя текстура 

      fixed4 frag(vertexOutput v):SV_Target 
      {
        fixed4 col = tex2D(_xgmTex,v.uv);// берем цвет из текстуры по UV
 координатам
        return col;
      } 

Ну вот и всё, наш шейдер готов!

Shader "MyShaders/xgmSkin" 
{
  Properties 
  {
    _xgmTex("Texture",2D) = "white" {} 
  }

SubShader
 {
   Pass
   {
     CGPROGRAM 
     #pragma vertex vert // говорим имя у вертексного шейдера 
     #pragma fragment frag  // говорим имя пиксельного шейдера

      struct vertexInput 
      {
        float4 vertex:POSITION;
        float2 uv:TEXCOORD0;
      };
      struct vertexOutput
      {
       float4 position:SV_POSITION;
       float2 uv:TEXCOORD0;
      };
      vertexOutput vert(vertexInput v) 
      {
        vertexOutput o; // возвращаемая структура 
        o.position = mul(UNITY_MATRIX_MVP,v.vertex); // переводим координаты
        из пространства модели в проекционное 
        o.uv = v.uv; // просто передаем uv координаты
        return o;
      }
      uniform sampler2D _xgmTex; // внешняя текстура 

      fixed4 frag(vertexOutput v):SV_Target
      {
        fixed4 col = tex2D(_xgmTex,v.uv); // берем цвет из текстуры по 
UV координатам
        return col;
      } 
     ENDCG  
   } 
  } 
  Fallback "Diffuse"
 } 

Пора применить его на объекте! Для того что-бы применить шейдер для
какого-либо объекта, нужно создать новый материал и назначить наш шейдер
в выпадающем окне материала(если вы не забыли, наш шейдер находится в MyShaders>xgmSkin)

#3 Vertex and Fragment Shader — Unity — DevTribe: Разработка игр

Теперь выберем нужную текстуру в окне материала.
Вуаля!

#3 Vertex and Fragment Shader — Unity — DevTribe: Разработка игр

Теперь,думаю,стоит немного усложнить наш шейдер.Добавим в блок
Properties цвет, что-бы иметь возможность вручную управлять цветом.

    _Color ("LogoColor",Color) = (0,0,0,0)

И объявим его внутри шейдера в том-же месте, где объявляли текстуру

 uniform fixed4 _Color;

Надеюсь,вы читали первую статью, ну вот ту часть про цвет ? В общем сейчас мы
хотим поколдовать с цветом.
В итоге я изменил одну строчку в пиксельном шейдере

      fixed4 frag(vertexOutput v):SV_Target
      {
        fixed4 col = tex2D(_xgmTex,v.uv); // берем цвет из текстуры по 
UV координатам
        return (1-col)*_Color;
      } 
1=(1,1,1,1); 0 = (0,0,0,0) //

В итоге,если мы установим _Color на зеленый цвет, у нас получилась
такая вот сфера, у которой мы можем менять цвет текстуры логотипа по
нашему желанию.)

#3 Vertex and Fragment Shader — Unity — DevTribe: Разработка игр

Итак, теперь мы, вроде, умеем делать простые-препростые шейдеры. Давайте
капнем немного глубже и сделаем нашей сфере дифузное освещение.
Вот формула, по которой рассчитывается освещенность для точки:
dif = max(0,(n*l)), где n - нормаль, l - направление света.

Заранее скажу, что рассчитывать освещение мы будет в мировых
координатах, следовательно, нормаль, которая дается в объектных
координатах придется переводить в мировые. Обычная матрица, которую мы
используем для частиц тут не подойдет, так-что для таких случаев
припасена встроенная инверсная матрица _World2Object.
Так-же хочу сказать о том, что в ShaderLab есть встроенная переменная
_WorldSpaceLightPos0. По названию можно понять, что это вектор, который
содержит мировые координаты источника света, но тут есть одна хитрость.
Если на карте используется только 1 источник света ( Direction light),
то тогда в эту переменную записывается вектор освещения, а если больше,
то ,действительно, положение источника света. В данном случае у нас один
источник, так что эта переменная нам подходит.
Еще кое-что.Как мы все знаем, семантика TEXCOORD используется для передачи
uv координат. Но, т.к. их может быть несколько штук, например,
TEXCOORD1,TEXCOORD2,TEXCOORD3..., ее удобно использовать, что-бы
передать нужные данные из вертексного шейдера в пиксельный, т.к. у
переменных во входящих/выходящих струтурах обязательно должна семантика.
Ну вот теперь вроде всё. Поехали!
Добавим в vertexInput строчку, которая будет запрашивать нормаль:

float3 norm:NORMAL;

И в vertexOutput переменную для хранения мировых координат нормали:

       float3 worldNormal:TEXCOORD1;

Далее идем в вертексный шейдер и переводим нормаль из объектного в
мировые координаты:

        o.worldNormal = mul(_World2Object,v.norm);

Ну и рассчитаем силу освещения в пиксельном шейдере:

      fixed4 frag(vertexOutput v):SV_Target
      {
        fixed4 col = tex2D(_xgmTex,v.uv); // берем цвет из текстуры по UV координатам
        float3 l = normalize(_WorldSpaceLightPos0); // нормализуем вектор освещения
        float3 n = normalize(v.worldNormal); // нормализуем вектор нормали 
        float dif = max(0.0,dot(n,l)); // рассчитываем освещенность пикселя 
        return ((1-col)*_Color)*dif; 
      } 

Ну вот как-то так. Теперь, если мы перейдем в юнити и изменим
направление лучей у Direction light'а, то заметим, что участки с
противоположной стороны от света затеняться.

#3 Vertex and Fragment Shader — Unity — DevTribe: Разработка игр

Shader "MyShaders/xgmSkin"
{
Properties
{
_xgmTex("Texture",2D) = "white" {}
_Color ("LogoColor",Color) = (0,0,0,0)
}

SubShader
{
Pass
{
Cull Off

CGPROGRAM
#pragma vertex vert // говорим имя у вертексного шейдера
#pragma fragment frag // говорим имя пиксельного шейдера

struct vertexInput
{
float4 vertex:POSITION;
float2 uv:TEXCOORD0;
float3 norm:NORMAL;
};
struct vertexOutput
{
float4 position:SV_POSITION;
float2 uv:TEXCOORD0;
float3 worldNormal:TEXCOORD1;
};
vertexOutput vert(vertexInput v)
{
vertexOutput o; // возвращаемая структура
o.position = mul(UNITY_MATRIX_MVP,v.vertex); // переводим координаты из пространства модели в проекционное
o.uv = v.uv; // просто передаем uv координаты
o.worldNormal = mul(_World2Object,v.norm); // переводим нормаль в мировые к-ты
return o;
}
uniform sampler2D _xgmTex; // внешняя текстура
uniform fixed4 _Color;

fixed4 frag(vertexOutput v):SV_Target
{
fixed4 col = tex2D(_xgmTex,v.uv); // берем цвет из текстуры по UV координатам
float3 l = normalize(_WorldSpaceLightPos0); // нормализуем вектор освещения
float3 n = normalize(v.worldNormal); // нормализуем вектор нормали
float dif = max(0.0,dot(n,l)); // рассчитываем освещенность пикселя
return ((1-col)*_Color)*dif;
}
ENDCG

}
}
Fallback "Diffuse"
}

Итог:

http://devtribe.ru/ext-files/562/174812/qwerty.unity3d

To be continued ...

P.S. спонсоры данных статьей - кофе и свободное время. Спасибо им за то что они есть.

Здесь еще никто не оставил комментарий