Anahat nesne efekti


26

League of Legends veya Diablo III'te bulunanlara benzer bir anahat efektini nasıl elde edebilirim?

Efsaneler Ligi Anahat Efsaneler Ligi Anahat Diablo III anahattı

Bir gölgelendirici kullanılarak mı yapıldı? Nasıl?
Herhangi bir motora bağlı olmayan ama üzerinde çalıştığım motora adapte olabileceğim cevapları tercih ederim.

Yanıtlar:


19

Sen edecek bir noktada iki kez nesneyi işlemek zorunda. Sadece bir kez kameraya bakan yüzleri ve bir kez kameradan bakan yüzleri görüntüleyerek kurtulabilirsiniz , ancak takası değişebilir.

En basit ortak çözüm, nesneyi aynı geçişte iki kez yapmak suretiyle yapılır:

  • Nesnenin normlarını ters çevirmek için tepe noktası gölgelendiricisi kullanır ve dış çizginin boyutuna göre "havaya uçurur" ve anahat renginde oluşturmak için bir parça gölgelendirici kullanırsınız
  • Bu anahat render üzerinde, nesneyi normal olarak yaratırsınız. Z sırası genellikle otomatik olarak doğru, aşağı yukarı doğrudur, çünkü ana hat, nesnenin "arkasındaki" yüzlerle yapılırken, figürün kendisi kameraya bakan yüzlerden oluşur.

Bu, herhangi bir dokuya dönüştürme püf noktası oluşturmak ve uygulamak ve bunları önlemek için yeterince basittir, ancak dikkat çeken birkaç dezavantajı vardır:

  • Anahat boyutu, kamerayla arasındaki mesafeye göre ölçeklendirme yapmazsanız değişkenlik gösterecektir. Uzaktaki nesneler yakındakilerden daha küçük bir taslak olacaktır. Tabii ki, aslında istediğin bu olabilir .
  • "Patlatmak" tepe gölgelendiricisi, örneğinizdeki iskelet gibi karmaşık nesneler için çok iyi çalışmaz, z dövüş artefaktlarını işleyiciye kolayca sunar. Bunu düzeltmek, nesneyi iki seferde oluşturmanızı gerektirir, ancak normalleri ters çevirmekten kurtarır.
  • Anahat ve nesne, diğer nesneler aynı alanı işgal ettiğinde çok iyi çalışmayabilir ve genel olarak yansıma ve kırılma gölgelendiricileriyle birleştirildiğinde doğru olması gereken bir acıdır.

Böyle bir gölgelendirici için temel fikir şöyle görünür (Birlik için Cg - kod - bir yerde bulduğum ve değiştirdiğim bir gölgelendiricidir, kaynağı not etmedim, bu yüzden hazır bir fikirden daha kötü yazılmış bir kavram kanıtı. kullanımlı gölgelendirici):

Shader "Basic Outline" {
    Properties {
        _Color ("Main Color", Color) = (.5,.5,.5,1)
        _OutlineColor ("Outline Color", Color) = (1,0.5,0,1)
        _Outline ("Outline width", Range (0.0, 0.1)) = .05
        _MainTex ("Base (RGB)", 2D) = "white" { }
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        Pass {
            Name "OUTLINE"
            Tags { "LightMode" = "Always" }
CGPROGRAM
#pragma exclude_renderers gles
#pragma exclude_renderers xbox360
#pragma vertex vert

struct appdata {
    float4 vertex;
    float3 normal;
};

struct v2f
{
    float4 pos : POSITION;
    float4 color : COLOR;
    float fog : FOGC;
};
float _Outline;
float4 _OutlineColor;
v2f vert(appdata v)
{
    v2f o;
    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    float3 norm = mul ((float3x3)UNITY_MATRIX_MV, v.normal);
    norm.x *= UNITY_MATRIX_P[0][0];
    norm.y *= UNITY_MATRIX_P[1][1];
    o.pos.xy += norm.xy * _Outline;
    o.fog = o.pos.z;
    o.color = _OutlineColor;
    return o;
}
ENDCG
            Cull Front
            ZWrite On
            ColorMask RGB
            Blend SrcAlpha OneMinusSrcAlpha
            SetTexture [_MainTex] { combine primary }
        }
        Pass {
        Name "BASE"
        Tags {"LightMode" = "Always"}
CGPROGRAM
#pragma fragment frag
#pragma vertex vert
#pragma fragmentoption ARB_fog_exp2
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"

struct v2f {
    float4 pos : SV_POSITION;
    float2    uv            : TEXCOORD0;
    float3    viewDir        : TEXCOORD1;
    float3    normal        : TEXCOORD2;
}; 

v2f vert (appdata_base v)
{
    v2f o;
    o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    o.normal = v.normal;
    o.uv = TRANSFORM_UV(0);
    o.viewDir = ObjSpaceViewDir( v.vertex );
    return o;
}

uniform float4 _Color;

uniform sampler2D _MainTex;
float4 frag (v2f i)  : COLOR
{
    half4 texcol = tex2D( _MainTex, i.uv );

    half3 ambient = texcol.rgb * (UNITY_LIGHTMODEL_AMBIENT.rgb);
    return float4( ambient, texcol.a * _Color.a );
}
ENDCG
    }
    }
    FallBack "Diffuse"
}

Diğer yaygın yöntem nesneyi de iki kez oluşturur, ancak tepe gölgelendiriciyi tamamen önler. Öte yandan, tek bir geçişte kolayca yapılamaz ve dokuya dönüştürülmesi gerekir: Nesneyi bir kez "düz" anahat renkli parça gölgelendirici ile bir kez oluşturun ve bu görüntü üzerinde (ağırlıklı) bir bulanıklık kullanın ekran boşluğundan sonra, nesneyi üzerine her zamanki gibi yerleştirin.

Ayrıca, GPU'ya biraz daha fazla vergi ayırması ve sanatçıların sizi oluşturmasını kolaylaştırmadıkça, uykunuzda sizi öldürmesini istemesine neden olacak olmasına rağmen, bu yöntemi uygulamak için üçüncü ve muhtemelen en kolay olanı var: her zaman ağlayın, sadece tamamen saydam veya görünmeyen bir yere (derin yeraltı gibi) ihtiyacınız olana kadar hareket ettirin


Şablon tamponu burada yaygın olarak kullanılan bir yaklaşım değil mi?
edA-qa mort-ora-y

1
@ edA-qamort-ora-y: Bu da işe yarayabilirdi, ama bu yaklaşımı hiç denemedim, bu yüzden yorum yapamam. :) Aklınızda bir çalışma algoritması varsa, bu yöntemi başka bir cevap olarak da eklemekten çekinmeyin.
Martin Sojka

Kendim hakkında daha fazla bir şey bilmiyorum, sadece stencil tamponlarına atıfta bulunulan anahatların sıkça bahsedildiğini. :) İlk yaklaşımınızın daha donanım temelli bir sürümü olabilir gibi görünüyor (iki geçiş, birincisi daha büyük).
edA-qa mort-ora-y

Şablon tamponu yaklaşımı, şablon tamponlarını güncellemek ve temizlemek için daha fazla bant genişliği kullanabilir ve çoklu geçişler gerektirir. Martin listeleri yaklaşımı bazı sınırlı durumlarda en fazla iki olmak üzere bir seferde yapılabilir ve ek bant genişliği için minimum bant genişliği gerekir.
Sean Middleditch

Bu yaklaşım (boyutu normal boyunca şişirmek) küp gibi nesnelerle (özellikle orto kamerayla) çalışmaz. Bunun bir çözümü var mı?
NPS

4

Martin Sojkas cevabına ek olarak, statik nesneler (veya sprite) için daha basit bir şeyle kurtulabilirsiniz.

Aynı sprite ancak dış çizgileri ile doku atlasınıza veya tamamen başka bir dokuya kaydederek geçişi kolaylaştırabilirsiniz. Bu aynı zamanda daha görsel olarak çekici veya sadece farklı görünen özel anahatlar yapmanızı da sağlayacaktır.

Diğer yöntem, sprite'ı biraz daha büyük olan tek bir renk şekli olarak kaydetmek ve sprite kendisini oluşturulmadan hemen önce kılmaktır. Bu size seçimin rengini kolayca değiştirme imkanı verecek ve # 1 yöntemi ile anahat sprite'larının gerektirdiği kadar farklı renk şekillerine ihtiyacınız olmayabilir.

Her ikisi de olsa hafıza ayak izinizi artıracak.


4

Martin Sojka'nın cevabına yapılan yorumlarda da belirtildiği gibi, FlipCode'da Max McGuire tarafından detaylandırıldığı gibi şablon veya derinlik tamponu kullanılarak da benzer bir etki elde edilebilir:

http://www.flipcode.com/archives/Object_Outlining.shtml

Temel olarak, şablon tamponunu sabit bir değere ayarlarken, artırılmış çizgi genişliğiyle (veya örneğin D3D'de olduğu gibi, bunun mümkün olmaması durumunda) özetlenen istediğiniz modelin bir tel kafes versiyonunu çiziyor.

Bu yaklaşım, bugünün OpenGL'sini kullanarak biraz tarihli olabilir ve nesne anahattının bulanık görünmesi için dokuya render yapılması hala gerekli olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.