Procedural Screen Quad

Лучший способ помочь другим, поделиться своими находками.

Procedural Screen Quad

Сообщение gnoblin 21 окт 2010, 21:47

Вступление:
надоело пользоваться всякими GL\Graphics (которые у меня постоянно не работают из-за кривых рук)...
Лучше рендерить квад в камеру, а потом выводить его в экранных координатах на процедурном плейнике!

Что делает скрипт:

Выводит в указанном ректе экрана квад с нужным материалом (если меняем рект - квад обновляется).
Планирую часто использовать эту технологию в работе, поэтому бекаплю здесь на всякий пожарный (и может кому-то будет полезно).

Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class ProceduralScreenQuad : MonoBehaviour
{
    public Rect rect = new Rect(100,100,256,256);
    Rect old_rect;

    MeshFilter mf;
    public Camera cam;
    void Start()
    {
        mf = gameObject.GetComponent<MeshFilter>();
        old_rect = rect;
        GenerateQuad(rect);
        //cam = Camera.main;

        // мега хак... репортнуть
        transform.Translate(new Vector3(0,0,0));
    }

    void Update()
    {
        if (rect != old_rect)
        {
            ChangeQuadRect(rect);
        }

        old_rect = rect;
    }

    void ChangeQuadRect(Rect newRect)
    {
        Vector2[] rect_points = GetPointsFromRect(newRect);
        Vector3[] verts = GetWorldPointsFromScreenPoints(rect_points);

        mf.mesh.vertices = verts;
    }

    void GenerateQuad(Rect newRect)
    {
        Mesh mesh = new Mesh();
       
        Vector2[] uvs = new Vector2[]{ new Vector2(0,0), new Vector2(1,0), new Vector2(0,1), new Vector2(1,1)};

        //1 quad * 2 triangles * 3 vert.indices per triangle
        int[] tris = new int[]{ 2,1,0,
                                3,1,2 };

        Vector2[] rect_points = GetPointsFromRect(newRect);
        Vector3[] verts = GetWorldPointsFromScreenPoints(rect_points);

        mesh.vertices = verts;
        mesh.uv = uvs;
        mesh.triangles = tris;
        mesh.RecalculateBounds();
        mesh.RecalculateNormals();
       
        mf.mesh = mesh;
    }

    Vector3[] GetWorldPointsFromScreenPoints(Vector2[] rect_points)
    {
        Vector3[] verts = new Vector3[4];
       
        for (int i = 0; i < 4; i++)
        {
            verts[i] = cam.ScreenToWorldPoint(new Vector3(rect_points[i].x, rect_points[i].y, 2f));
            verts[i] = transform.InverseTransformPoint(verts[i]);
        }

        return verts;
    }

    Vector2[] GetPointsFromRect(Rect newRect)
    {
        Vector2[] points = new Vector2[4];
        points[0] = new Vector2(newRect.x, newRect.y);
        points[1] = new Vector2(newRect.xMax, newRect.y);
        points[2] = new Vector2(newRect.x, newRect.yMax);
        points[3] = new Vector2(newRect.xMax, newRect.yMax);
        return points;
    }
}
 
У вас нет доступа для просмотра вложений в этом сообщении.
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Procedural Screen Quad

Сообщение gnoblin 21 окт 2010, 21:55

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

Re: Procedural Screen Quad

Сообщение GrueGames 21 окт 2010, 22:39

В редакторе параметры экрана не совпадают с билдом и зависят то того как растянешь панельки в гуе.
Достало это, нет кстати случайно идеи как пофиксить?
Аватара пользователя
GrueGames
UNITрон
 
Сообщения: 200
Зарегистрирован: 11 апр 2009, 16:42
Откуда: Samara, Russia
  • Сайт
  • ICQ

Re: Procedural Screen Quad

Сообщение gnoblin 22 окт 2010, 15:30

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

Re: Procedural Screen Quad

Сообщение Neodrop 22 окт 2010, 22:43

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

Re: Procedural Screen Quad

Сообщение gnoblin 21 дек 2010, 18:47

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

Re: Procedural Screen Quad

Сообщение gnoblin 21 дек 2010, 18:48

Для задания глубины квада относительно камеры можно вместо 2f использовать отдельный параметр public float z; или брать это значение из transform.position.z :)
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт

Re: Procedural Screen Quad

Сообщение gnoblin 21 дек 2010, 18:51

Можно масштабировать квад при изменении разрешения экрана относительно целевого.

Синтаксис:
Используется csharp
public bool scaleWithResolution;

Vector3[] GetWorldPointsFromScreenPoints(Vector2[] rect_points)
    {
        Vector3[] verts = new Vector3[4];

        float screen_k = 1f;

        if (scaleWithResolution)
        {
            screen_k = Screen.height / 768f;
        }

        for (int i = 0; i < 4; i++)
        {
            verts[i] = cam.ScreenToWorldPoint(new Vector3(rect_points[i].x * screen_k, rect_points[i].y * screen_k, transform.position.z));
            verts[i] = transform.InverseTransformPoint(verts[i]);
        }

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

Re: Procedural Screen Quad

Сообщение gnoblin 21 дек 2010, 21:26

Немного другой вариант скрипта,
теперь плейник тягается за пивотом.

Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;

//надоело пользоваться всякими GL\Graphics (которые у меня постоянно не работают из-за кривых рук)...
//Лучше рендерить квад в камеру, а потом выводить его в экранных координатах на процедурном плейнике!
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
[ExecuteInEditMode]
public class ProceduralScreenQuad : MonoBehaviour
{
    public Vector2 size = new Vector2(256, 256);
    //public Rect rect = new Rect(100,100,256,256);
    //Rect old_rect;
    Vector2 old_size;
    float old_z;

    public bool scaleWithResolution;

    MeshFilter mf;
    public Camera cam;
    void Start()
    {
        mf = gameObject.GetComponent<MeshFilter>();
        //old_rect = rect;
        old_size = size;
        old_z = Z;

        FindRect(size);
        //cam = Camera.main;

        // мега хак... репортнуть
        transform.Translate(new Vector3(0, 0, 0));
    }

    float Z
    {
        get
        {
            return transform.position.z;
        }
    }

    void Update()
    {
        //if (rect != old_rect)
        if (size != old_size || Z != old_z)
        {
            FindRect(size);
            //old_rect = rect;
            old_size = size;
            old_z = Z;
        }
    }
    Rect rect;
    void FindRect(Vector2 _size)
    {
        //create a rect with 'size' around transform.position
        Vector3 scr = cam.WorldToScreenPoint(transform.position);
       
        rect = new Rect(scr.x - 0.5f*size.x, scr.y - 0.5f*size.y, size.x, size.y);

        //rect = new Rect(scr.x, scr.y, size.x, scr.y + half_size.y);

        ChangeQuadRect(rect);
    }

    void ChangeQuadRect(Rect newRect)
    {
        Vector2[] rect_points = GetPointsFromRect(newRect);
        Vector3[] verts = GetWorldPointsFromScreenPoints(rect_points);

        mf.sharedMesh.vertices = verts;
    }

    void GenerateQuad(Rect newRect)
    {
        Mesh mesh = new Mesh();

        Vector2[] uvs = new Vector2[] { new Vector2(0, 0), new Vector2(1, 0), new Vector2(0, 1), new Vector2(1, 1) };

        //1 quad * 2 triangles * 3 vert.indices per triangle
        int[] tris = new int[]{ 2,1,0,
                                3,1,2 };

        Vector2[] rect_points = GetPointsFromRect(newRect);
        Vector3[] verts = GetWorldPointsFromScreenPoints(rect_points);

        mesh.vertices = verts;
        mesh.uv = uvs;
        mesh.triangles = tris;
        mesh.RecalculateBounds();
        mesh.RecalculateNormals();

        mf.sharedMesh = mesh;
    }

    Vector3[] GetWorldPointsFromScreenPoints(Vector2[] rect_points)
    {
        Vector3[] verts = new Vector3[4];

        float screen_k = 1f;

        if (scaleWithResolution)
        {
            screen_k = Screen.height / 768f;
        }

        for (int i = 0; i < 4; i++)
        {
            verts[i] = cam.ScreenToWorldPoint(new Vector3(rect_points[i].x * screen_k, rect_points[i].y * screen_k, Z));
            verts[i] = transform.InverseTransformPoint(verts[i]);
        }

        return verts;
    }

    Vector2[] GetPointsFromRect(Rect newRect)
    {
        Vector2[] points = new Vector2[4];
        points[0] = new Vector2(newRect.x, newRect.y);
        points[1] = new Vector2(newRect.xMax, newRect.y);
        points[2] = new Vector2(newRect.x, newRect.yMax);
        points[3] = new Vector2(newRect.xMax, newRect.yMax);
        return points;
    }
}
 
skypeid: madkust
Мои крайние проекты:
Убойный Хоккей
Cube Day Z (альфа)
Аватара пользователя
gnoblin
Адепт
 
Сообщения: 4633
Зарегистрирован: 08 окт 2008, 17:23
Откуда: Минск, Беларусь
Skype: madkust
  • Сайт


Вернуться в Исходники (Копилка)

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

Сейчас этот форум просматривают: Yandex [Bot] и гости: 0