1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/Sun_ME-Billboard

В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
readme.md

Реализация эффекта рекламного щита, при котором полигон всегда смотрит в сторону камеры при её вращении.

Пример эффекта представлен на скриншоте ниже.

Один из шейдеров, реализующих этот эффект

(взят из книги Фэн Цзы "Unity Shader: Учебное пособие" глава 11.3.2)
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP, *)' with 'UnityObjectToClipPos(*)'```markdown
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
```shadere "Unlit/fll-Billboard" {
	Свойства {
		_MainTex ("Основное изображение", 2D) = "white" {}
		_Color ("Цветовая накладка", Color) = (1, 1, 1, 1)
		_VerticalBillboarding ("Вертикальные ограничения", Range(-5, 5)) = 2
	}
	Подшейдер {
		// Необходимо отключить пакетирование из-за вершинной анимации
		Теги {"Очередь"="Прозрачный" "Игнорировать проектор"="Истина" "Тип рендера"="Прозрачный" "Отключить пакетирование"="Истина"}
		Скрыть обратную сторону от
		Пропускать запись Z
		CGPROGRAM
		#pragma вершина vert
		#pragma фрагмент frag
		#include "Lighting.cginc"
		sampler2D _MainTex;
		float4 _MainTex_ST;
		fixed4 _Color;
		fixed _VerticalBillboarding;
		struct a2v {
			float4 вершина : POSITION;
			float4 текстура : TEXCOORD0;
		};
		struct v2f {
			float4 pos : SV_POSITION;
			float2 uv : TEXCOORD0;
		};
		v2f vert (a2v v) {
			v2f o;
			// Предполагаем, что центр в пространстве объекта фиксирован
			float3 center = float3(0, 0, 0);
			float3 viewer = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));
			float3 normalDir = viewer - center;
			// Если _VerticalBillboarding равно 1, мы используем желаемое направление просмотра как направление нормали
			// То есть направление нормали фиксировано
			// Или если _VerticalBillboarding равно 0, y нормали равно 0
			// То есть направление верха фиксировано
			normalDir.y = normalDir.y * _VerticalBillboarding;
			normalDir = normalize(normalDir);
			// Получаем приближенное направление верха
			// Если направление нормали уже направлено вверх, то направление верха направлено вперед
			float3 upDir = abs(normalDir.y) > 0.999 ? float3(0, 0, 1) : float3(0, 1, 0);
			float3 rightDir = normalize(cross(upDir, normalDir)) * -1;
			upDir = normalize(cross(normalDir, rightDir));
```			// Используем три вектора для вращения квадрата
 			float3 centerOffs = v. вершина. xyz - center;
 			float3 localPos = center + rightDir * centerOffs. x + upDir * centerOffs. y + normalDir * centerOffs. z;
  			o. pos = UnityObjectToClipPos(float4(localPos, 1));
 			o. uv = TRANSFORM_TEX(v. текстура, _MainTex);```c++
 				return o;
 			}
  			fixed4 frag (v2f i) : SV_Target {
 				fixed4 c = tex2D (_MainTex, i. uv);
 				c. rgb *= _Color. rgb;
  				return c;
 			}
  			ENDCG
 		}
 	} 
 	FallBack "Transparent/VertexLit"
 }```
***Обратите внимание: в коде есть место, которое необходимо изменить, как показано ниже:***

```c++
v2f vert (a2v v) {
    //*****
    float3 rightDir = normalize(cross(upDir, normalDir)) * -1;
    //*****
}

Умножение на -1 меняет направление, иначе в Unity могут возникнуть проблемы с переворотом.

Второй шейдер, реализованный с использованием Cg

Исходный код взят из Wiki Cg_Programming (https://en.wikibooks.org/wiki/Cg_Programming/Unity/Billboards)

Исходный код:

Шейдер "Cg шейдер для бильбордов" {
   Свойства {
      _MainTex ("Текстура изображения", 2D) = "white" {}
      _ScaleX ("Масштаб X", Float) = 1.0
      _ScaleY ("Масштаб Y", Float) = 1.0
   }
   Подшейдер {
      Пропасс {   
         CGPROGRAM
 
         #pragma vertex vert  
         #pragma fragment frag

         // Пользовательские переменные            
         uniform sampler2D _MainTex;        
         uniform float _ScaleX;
         uniform float _ScaleY;

         struct vertexInput {
            float4 вершина : POSITION;
            float4 текст : TEXCOORD0;
         };
         struct vertexOutput {
            float4 pos : SV_POSITION;
            float4 текст : TEXCOORD0;
         };
 
         vertexOutput vert(vertexInput вход) 
         {
            vertexOutput выход;

            выход.pos = mul(UNITY_MATRIX_P, 
              mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
              + float4(вход.вершина.x, вход.вершина.y, 0.0, 0.0)
              * float4(_ScaleX, _ScaleY, 1.0, 1.0));
 
            выход.текст = вход.текст;
         }
 
         half4 frag(vertexOutput выход) : COLOR {
            half4 цвет = tex2D(_MainTex, выход.текст);
            return цвет;
         }
 
         ENDCG
      }
   }
}
```            возвращаем выход;
         }
 
         float4 frag(vertexOutput вход) : COLOR
         {
            возвращаем tex2D(_MainTex, float2(вход.текст.xy));   
         }
 
         ENDCG
      }
   }
}

Этот код имеет некоторые ограничения:

  1. Не поддерживает канал прозрачности.
  2. При включении шейдером функции батчинга могут возникнуть проблемы отображения, то есть, когда объект находится далеко от камеры, он может быть обрезан.
  3. Не поддерживает масштабирование и трансформацию объекта в интерфейсе Unity Transform.## Модифицированный код представлен ниже:
Шейдер "Unlit/fll-Billboard-2" {
   Свойства {
      _MainTex ("Текстура изображения", 2D) = "white" {}
      _ScaleX ("Масштаб X", Float) = 1.0
      _ScaleY ("Масштаб Y", Float) = 1.0
      _Color ("Цвет", Color) = (1, 1, 1, 1)
   }
   Подшейдер {
      Теги {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "DisableBatching"="True"}
      Пропуск {    
         Теги { "DisableBatching" = "True" }
         ZWrite On
         Blend SrcAlpha OneMinusSrcAlpha
         Cull Off
      }
   }
}
CGPROGRAM

#pragma vertex vert  
#pragma fragment frag
#include "Lighting.cginc"

// Пользовательские uniforms            
uniform sampler2D _MainTex;        
uniform float _ScaleX;
uniform float _ScaleY;
uniform fixed4 _Color;
uniform float4 _MainTex_ST;

struct vertexInput {
    float4 vertex : POSITION;
    float4 tex : TEXCOORD0;
};

struct vertexOutput {
    float4 pos : SV_POSITION;
    float2 tex : TEXCOORD0;
};

vertexOutput vert(vertexInput input) 
{
    vertexOutput output;

    output.pos = mul(UNITY_MATRIX_P, 
        mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
        + float4(input.vertex.x, input.vertex.y, 0.0, 0.0)
        * float4(_ScaleX, _ScaleY, 1.0, 1.0));
 
    output.tex = TRANSFORM_TEX(input.tex, _MainTex);
    return output;
}

float4 frag(vertexOutput input) : SV_Target
{
    fixed4 c = tex2D(_MainTex, float2(input.tex.xy));
    c.rgb *= _Color.rgb;
    return c;
}
ENDCG
}

Код для отрисовки линии от головы персонажа до полигонов:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
``````csharp
public class DrawLineRender : MonoBehaviour {
    public Color materialColor;
    LineRenderer lineRenderer_global;
    Vector3 startPos;
    Vector3 endPos;
    Vector3[] poss;
    [SerializeField]
    private Vector3 offset = Vector3.zero;
    [SerializeField]
    [Range(0f, 0.2f)]
    private float width = 0.1f;
    
    void Awake () {
        LineRenderer lineRenderer = this.gameObject.AddComponent<LineRenderer> ();
        Material material = new Material(Shader.Find("Unlit/Color"));
        lineRenderer.material = material;
        lineRenderer.material.color = materialColor;
        lineRenderer.widthMultiplier = width;
        lineRenderer.positionCount = 2;
        lineRenderer.numCornerVertices = 30;
        lineRenderer.numCapVertices = 30;
    }
}
``````csharp
        startPos = this.transform.parent.GetChild(2).transform.localPosition;
        endPos = this.transform.parent.GetChild(0).transform.localPosition;
        //var offset = new Vector3(0, 1.254f, 0);
        poss = new Vector3[2] { startPos - offset, endPos - offset };
    }

    void Start()
    {
        lineRenderer_global = this.GetComponent<LineRenderer>();
    }

    void Update()
    {
    }
}
``````markdown
```csharp
        for (int i = 0; i < lineRenderer_global.positionCount; i++) {
            lineRenderer_global.SetPosition(i, poss[i]);
        }
    }
}

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

Реализация эффекта рекламных щитов с помощью шейдеров Развернуть Свернуть
Отмена

Обновления

Пока нет обновлений

Участники

все

Язык

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/Sun_ME-Billboard.git
git@api.gitlife.ru:oschina-mirror/Sun_ME-Billboard.git
oschina-mirror
Sun_ME-Billboard
Sun_ME-Billboard
master