Özet
Mobil kontrollü yüksek performanslı bir WebGL web sitesi oluşturmak için Polymer'i nasıl kullandık? Modüler ve yapılandırılabilir ışın kılıcı. Bir dahaki sefere öfkeli Stormtrooper'lara rastladığınızda kendi ışın kılıcınızı oluştururken zaman kazanmanıza yardımcı olmak için https://lightsaber.withgoogle.com/ projemizin bazı önemli ayrıntılarını inceliyoruz.
Genel Bakış
Polymer veya WebComponents'in ne olduğunu merak ediyorsanız gerçek bir çalışma projesinden bir kesit paylaşarak başlamanın en iyi olacağını düşündük. Burada projemizin açılış sayfasından alınmış bir örnek https://lightsaber.withgoogle.com. İnsanların içeren, normal bir HTML dosyası oluşturun, ancak içinde biraz sihir var:
<!-- Element-->
<dom-module id="sw-page-landing">
<!-- Template-->
<template>
<style>
<!-- include elements/sw/pages/sw-page-landing/styles/sw-page-landing.css-->
</style>
<div class="centered content">
<sw-ui-logo></sw-ui-logo>
<div class="connection-url-wrapper">
<sw-t key="landing.type" class="type"></sw-t>
<div id="url" class="connection-url">.</div>
<sw-ui-toast></sw-ui-toast>
</div>
</div>
<div class="disclaimer epilepsy">
<sw-t key="disclaimer.epilepsy" class="type"></sw-t>
</div>
<sw-ui-footer state="extended"></sw-ui-footer>
</template>
<!-- Polymer element script-->
<script src="scripts/sw-page-landing.js"></script>
</dom-module>
Bu nedenle, günümüzde HTML5 tabanlı bir uygulama oluşturmak için birçok seçenek mevcuttur. API'ler, Çerçeveler, Kitaplıklar, Oyun Motorları vb. Tüm seçeneklere rağmen kaliteli ve uygun bir kurulum bulmak zor. yüksek performanslı grafik performansı ile temiz modüler yapı ve ölçeklenebilirlik. Polymer'in çevreyi korumamıza yardımcı olabileceğini düşük düzeyli performansa izin verecek şekilde organize edilmişse parçalama şeklimizi dikkatli bir şekilde oluşturduk. bileşenlerine ayırmanızı sağlar.
Polimer ile Modülerlik
Polymer, bir ve yeniden kullanılabilir özel öğelerden projenizin oluşturulma şekli üzerinde çok fazla güce sahip olmanız gerekir. Tek bir pakette bulunan bağımsız, tam işlevli modülleri kullanmanıza olanak tanır. tek HTML dosyası olabilir. Bunlar, yalnızca yapıyı (HTML işaretlemesi) değil, satır içi stiller ve mantık.
Aşağıdaki örneği inceleyin:
<link rel="import" href="bower_components/polymer/polymer.html">
<dom-module id="picture-frame">
<template>
<!-- scoped CSS for this element -->
<style>
div {
display: inline-block;
background-color: #ccc;
border-radius: 8px;
padding: 4px;
}
</style>
<div>
<!-- any children are rendered here -->
<content></content>
</div>
</template>
<script>
Polymer({
is: "picture-frame",
});
</script>
</dom-module>
Ama daha büyük bir projede bu üç mantıksal (HTML, CSS, JS) düzenleyebilir ve yalnızca derleme sırasında birleştirir. Tek bir nokta projedeki her öğeye ayrı birer klasör vermek istedik:
src/elements/
|-- elements.jade
`-- sw
|-- debug
| |-- sw-debug
| |-- sw-debug-performance
| |-- sw-debug-version
| `-- sw-debug-webgl
|-- experience
| |-- effects
| |-- sw-experience
| |-- sw-experience-controller
| |-- sw-experience-engine
| |-- sw-experience-input
| |-- sw-experience-model
| |-- sw-experience-postprocessor
| |-- sw-experience-renderer
| |-- sw-experience-state
| `-- sw-timer
|-- input
| |-- sw-input-keyboard
| `-- sw-input-remote
|-- pages
| |-- sw-page-calibration
| |-- sw-page-connection
| |-- sw-page-connection-error
| |-- sw-page-error
| |-- sw-page-experience
| `-- sw-page-landing
|-- sw-app
| |-- bower.json
| |-- scripts
| |-- styles
| `-- sw-app.jade
|-- system
| |-- sw-routing
| |-- sw-system
| |-- sw-system-audio
| |-- sw-system-config
| |-- sw-system-environment
| |-- sw-system-events
| |-- sw-system-remote
| |-- sw-system-social
| |-- sw-system-tracking
| |-- sw-system-version
| |-- sw-system-webrtc
| `-- sw-system-websocket
|-- ui
| |-- experience
| |-- sw-preloader
| |-- sw-sound
| |-- sw-ui-button
| |-- sw-ui-calibration
| |-- sw-ui-disconnected
| |-- sw-ui-final
| |-- sw-ui-footer
| |-- sw-ui-help
| |-- sw-ui-language
| |-- sw-ui-logo
| |-- sw-ui-mask
| |-- sw-ui-menu
| |-- sw-ui-overlay
| |-- sw-ui-quality
| |-- sw-ui-select
| |-- sw-ui-toast
| |-- sw-ui-toggle-screen
| `-- sw-ui-volume
`-- utils
`-- sw-t
Her bir öğenin klasörü, aynı iç yapıya sahiptir ve ayrı ayrı öğeler mantık (kahve dosyaları), stiller (scss dosyaları) ve şablonunu (yeşim dosyası) tıklayın.
Aşağıda örnek bir sw-ui-logo
öğesi verilmiştir:
sw-ui-logo/
|-- bower.json
|-- scripts
| `-- sw-ui-logo.coffee
|-- styles
| `-- sw-ui-logo.scss
`-- sw-ui-logo.jade
.jade
dosyasına bakarsanız:
// Element
dom-module(id='sw-ui-logo')
// Template
template
style
include elements/sw/ui/sw-ui-logo/styles/sw-ui-logo.css
img(src='[[url]]')
// Polymer element script
script(src='scripts/sw-ui-logo.js')
Stilleri kullanarak öğelerin nasıl düzenli bir şekilde düzenlendiğini görebilirsiniz
mantığı ve bunu kullanır. Stillerimizi Polymer öğelerimize dahil etmek için Jade'ın include
ifadesini kullanırız. Böylece derleme işleminden sonra gerçek satır içi CSS dosya içeriğine sahip oluruz. sw-ui-logo.js
komut dosyası öğesi,
çalışma zamanında yürütür.
Bower ve Modüler Bağımlılıklar
Normalde kitaplıkları ve diğer bağımlılıkları proje düzeyinde tutarız.
Ancak yukarıdaki kurulumda, öğenin klasöründe bir bower.json
olduğunu fark edeceksiniz: öğe düzeyinde bağımlılıklar. Bu yaklaşımın arkasındaki fikir, farklı bağımlılıklara sahip çok sayıda öğenizin olduğu bir durumda yalnızca gerçekten kullanılan bağımlılıkları yüklediğinizden emin olabilmenizdir. Bir öğeyi kaldırdığınızda,
bower.json
dosyasını da kaldırmış olacağınızdan bağımlılığını kaldırın
açıklayacağım. Her öğe, kendisiyle ilgili bağımlılıkları bağımsız olarak yükler.
Bununla birlikte, bağımlılıkların yinelenmesini önlemek için bir .bowerrc
dosyası ekleriz.
her bir öğenin klasöründe de bulabilirsiniz. Bu, çarşafın nereye saklanacağını gösterir
Böylece aynı projenin sonunda yalnızca bir tane
olduğundan emin olabiliriz.
dizin:
{
"directory" : "../../../../../bower_components"
}
Bu sayede, birden fazla öğe THREE.js
'ü bağımlılık olarak belirtirse bower, öğeyi ilk öğe için yükledikten ve ikinci öğeyi ayrıştırmaya başladıktan sonra bu bağımlığın zaten yüklü olduğunu anlar ve öğeyi yeniden indirmez veya kopyalama yapmaz. Benzer şekilde, bu bağımlılığın
öğe tanımlamaya devam eden en az bir öğe olduğu sürece dosyaları,
bower.json
.
Bir bash komut dosyası, iç içe yerleştirilmiş öğe yapısındaki tüm bower.json
dosyalarını bulur.
Daha sonra bu dizinleri tek tek girer ve bower install
komutunu
her biri:
echo installing bower components...
modules=$(find /vagrant/app -type f -name "bower.json" -not -path "*node_modules*" -not -path "*bower_components*")
for module in $modules; do
pushd $(dirname $module)
bower install --allow-root -q
popd
done
Hızlı Yeni Öğe Şablonu
Yeni bir öğe oluşturmak istediğiniz her seferde biraz zaman alır. klasör ve temel dosya yapısının doğru adlara sahip olmasını sağlayın. Bu yüzden, Basit bir öğe oluşturucu yazmak için Slush.
Komut dosyasını, komut satırından çağırabilirsiniz:
$ slush element path/to/your/element-name
Tüm dosya yapısı ve içeriği de dahil olmak üzere yeni öğe oluşturulur.
Öğe dosyaları için şablonlar tanımladık. Örneğin, .jade
dosya şablonu aşağıdaki gibi görünür:
// Element
dom-module(id='<%= name %>')
// Template
template
style
include elements/<%= path %>/styles/<%= name %>.css
span This is a '<%= name %>' element.
// Polymer element script
script(src='scripts/<%= name %>.js')
Slush oluşturucu, değişkenleri gerçek öğe yolları ve adlarıyla değiştirir.
Nesne Oluşturmak için Gulp Kullanma
Gulp, derleme işlemini kontrol altında tutar. Yapımızda, öğeleri oluşturmak için Gulp'un aşağıdaki adımları uygulaması gerekir:
- Öğeleri derleyin
.js
hedefine.coffee
dosya - Öğeleri derleyin
.css
hedefine.scss
dosya - Öğeleri derleyin
.jade
dosya,.html
hedefine.css
dosya yerleştiriliyor.
Daha ayrıntılı olarak:
Öğeleri derleme .js
hedefine .coffee
dosya
gulp.task('elements-coffee', function () {
return gulp.src(abs(config.paths.app + '/elements/**/*.coffee'))
.pipe($.replaceTask({
patterns: [{json: getVersionData()}]
}))
.pipe($.changed(abs(config.paths.static + '/elements'), {extension: '.js'}))
.pipe($.coffeelint())
.pipe($.coffeelint.reporter())
.pipe($.sourcemaps.init())
.pipe($.coffee({
}))
.on('error', gutil.log)
.pipe($.sourcemaps.write())
.pipe(gulp.dest(abs(config.paths.static + '/elements')));
});
2. ve 3. adımlarda scss
öğesini aşağıdaki türlerde derlemek için gulp ve bir pusula eklentisi kullanırız:
.css
ve .jade
, yukarıdaki 2'ye benzer bir yaklaşımla .html
içine atanır.
Polimer Öğeler Dahil
Polimer öğelerini eklemek için HTML içe aktarmalarını kullanırız.
<link rel="import" href="elements.html">
<!-- Polymer -->
<link rel="import" href="../bower_components/polymer/polymer.html">
<!-- Custom elements -->
<link rel="import" href="sw/sw-app/sw-app.html">
<link rel="import" href="sw/system/sw-system/sw-system.html">
<link rel="import" href="sw/system/sw-routing/sw-routing.html">
<link rel="import" href="sw/system/sw-system-version/sw-system-version.html">
<link rel="import" href="sw/system/sw-system-environment/sw-system-environment.html">
<link rel="import" href="sw/pages/sw-page-landing/sw-page-landing.html">
<link rel="import" href="sw/pages/sw-page-connection/sw-page-connection.html">
<link rel="import" href="sw/pages/sw-page-calibration/sw-page-calibration.html">
<link rel="import" href="sw/pages/sw-page-experience/sw-page-experience.html">
<link rel="import" href="sw/ui/sw-preloader/sw-preloader.html">
<link rel="import" href="sw/ui/sw-ui-overlay/sw-ui-overlay.html">
<link rel="import" href="sw/ui/sw-ui-button/sw-ui-button.html">
<link rel="import" href="sw/ui/sw-ui-menu/sw-ui-menu.html">
Polimer öğelerini üretim için optimize etme
Büyük bir projede çok fazla Polymer öğe olabilir. Şurada:
elliden fazla örnek verilebilir. Her öğenin kendine özgü bir
ayrı .js
dosyası ve bazı kitaplıklara referansta bulunursanız bu dosya
100 ayrı dosya. Bu, tarayıcının yapması gereken çok sayıda istek
performans kaybı yaşanır. Benzer şekilde, bir süreci tamamlamak için
bir Angular yapısına başvuracak olursak, Polymer projesini
sonlandırılması gerekir.
Vulcanize, bağımlılık ağacını tek bir HTML dosyasına düzleştirerek istek sayısını azaltan bir Polymer aracıdır. Bu özellik, özellikle web bileşenlerini doğal olarak desteklemeyen tarayıcılar için idealdir.
CSP (İçerik Güvenliği Politikası) ve Polymer
Güvenli web uygulamaları geliştirirken CSP'yi uygulamanız gerekir. CSP siteler arası komut dosyası çalıştırma (XSS) saldırılarını engelleyen bir kurallar kümesidir: güvenli olmayan kaynaklardan komut dosyalarının yürütülmesi veya satır içi komut dosyalarının çalıştırılması başka bir dosya türü olabilir.
Optimize edilmiş, birleştirilmiş ve küçültülmüş .html
dosyası oluşturuldu
tarafından sunulan Vulcanize, tüm JavaScript kodunu CSP uyumlu olmayan bir satır içi olarak
biçimindedir. Bu sorunu gidermek için
Crisper.
Crisper, bir HTML dosyasından satır içi komut dosyalarını böler ve bunları tek bir komut dosyasına yerleştirir.
CSP uyumluluğu için harici JavaScript dosyası. Bu nedenle, vulkanize
bir HTML dosyası oluşturacaksınız ve sonuçta iki dosya olacak: elements.html
ve
elements.js
. elements.html
içinde ayrıca,
elements.js
gelir sağladı.
Uygulamanın Mantıksal Yapısı
Polimer'de öğeler, görsel olmayan bir yardımcıdan küçüğe kadar her şey olabilir. kullanıcı arayüzü öğeleri (düğmeler gibi) gibi daha büyük modüllere "sayfalar" ve hatta tam uygulamalar oluşturabilirsiniz.
Polimer ve Üst-Alt Mimari ile Son İşleme
Her 3D grafik ardışık düzeninde efektlerin etkilendiği son bir adım vardır. bir tür bindirme olarak tüm resmin üzerine eklenir. Bu, ve ışıltılar, tanrı ışınları, cisim ışınları arka plan resmi, bokeh, bulanıklaştırma vb. sahnenin nasıl oluşturulduğuna bağlı olarak farklı öğelerden faydalanır. THREE.js'de, JavaScript'te işleme sonrası için özel bir gölgelendirici oluşturabilir veya bunu, üst-alt yapısı sayesinde Polymer ile yapabiliyoruz.
Son işlemcimizin öğe HTML koduna bakarsanız:
<dom-module id="sw-experience-postprocessor">
<!-- Template-->
<template>
<sw-experience-effect-bloom class="effect"></sw-experience-effect-bloom>
<sw-experience-effect-dof class="effect"></sw-experience-effect-dof>
<sw-experience-effect-vignette class="effect"></sw-experience-effect-vignette>
</template>
<!-- Polymer element script-->
<script src="scripts/sw-experience-postprocessor.js"></script>
</dom-module>
Etkileri, ortak bir sınıf altında iç içe yerleştirilmiş Polymer öğeleri olarak belirtiriz. Ardından,
sw-experience-postprocessor.js
içinde şu işlemi gerçekleştiriyoruz:
effects = @querySelectorAll '.effect'
@composer.addPass effect.getPass() for effect in effects
Tüm URL'leri bulmak için HTML özelliğini ve JavaScript'in querySelectorAll
son işlemci içinde HTML öğeleri olarak iç içe yerleştirilmiş efektler
bir dizi dokümandır. Daha sonra bunları tekrarlayıp besteciye ekleriz.
Şimdi, DOF (Alan Derinliği) etkisini kaldırmak ve çiçeklenme ve vinyet efektlerinin sırasını değiştirebilirsiniz. Tek yapmamız gereken tanımlamayı şöyle özetleyebiliriz:
<dom-module id="sw-experience-postprocessor">
<!-- Template-->
<template>
<sw-experience-effect-vignette class="effect"></sw-experience-effect-vignette>
<sw-experience-effect-bloom class="effect"></sw-experience-effect-bloom>
</template>
<!-- Polymer element script-->
<script src="scripts/sw-experience-postprocessor.js"></script>
</dom-module>
ve sahne, gerçek kodda tek bir satır bile değiştirmeden çalışır.
Polymer'de döngü oluşturma ve güncelleme döngüsü
Polymer ile oluşturma ve motor güncellemelerine de zarif bir şekilde yaklaşabiliriz.
requestAnimationFrame
ve hesaplama işlemleri kullanan bir timer
öğesi oluşturduk
geçerli saat (t
) ve delta süresi -
son kare (dt
):
Polymer
is: 'sw-timer'
properties:
t:
type: Number
value: 0
readOnly: true
notify: true
dt:
type: Number
value: 0
readOnly: true
notify: true
_isRunning: false
_lastFrameTime: 0
ready: ->
@_isRunning = true
@_update()
_update: ->
if !@_isRunning then return
requestAnimationFrame => @_update()
currentTime = @_getCurrentTime()
@_setT currentTime
@_setDt currentTime - @_lastFrameTime
@_lastFrameTime = @_getCurrentTime()
_getCurrentTime: ->
if window.performance then performance.now() else new Date().getTime()
Ardından, t
ve dt
özelliklerini
motor (experience.jade
):
sw-timer(
t='{ % templatetag openvariable % }t}}',
dt='{ % templatetag openvariable % }dt}}'
)
sw-experience-engine(
t='[t]',
dt='[dt]'
)
Motorda t
ve dt
değişikliklerini de
değeri değiştiğinde _update
işlevi şu şekilde çağrılır:
Polymer
is: 'sw-experience-engine'
properties:
t:
type: Number
dt:
type: Number
observers: [
'_update(t)'
]
_update: (t) ->
dt = @dt
@_physics.update dt, t
@_renderer.render dt, t
Ancak FPS için can atıyorsanız öğeleri değişiklikler hakkında bilgilendirmek için gereken birkaç milisaniyeyi kurtarmak amacıyla Polymer'in veri bağlamasını oluşturma döngüsünden kaldırabilirsiniz. Özel gözlemcileri aşağıdaki şekilde uyguladık:
sw-timer.coffee
:
addUpdateListener: (listener) ->
if @_updateListeners.indexOf(listener) == -1
@_updateListeners.push listener
return
removeUpdateListener: (listener) ->
index = @_updateListeners.indexOf listener
if index != -1
@_updateListeners.splice index, 1
return
_update: ->
# ...
for listener in @_updateListeners
listener @dt, @t
# ...
addUpdateListener
işlevi bir geri çağırmayı kabul eder ve
geri çağırma dizisidir. Daha sonra, güncelleme döngüsünde her geri çağırmayı tekrar tekrar
veri bağlamayı atlayarak veya doğrudan dt
ve t
bağımsız değişkenleriyle yürütüyoruz.
etkinleşen etkinlik için de geçerlidir. Geri aramanın artık etkin olmaması gerektiğinde
Daha önce eklenen bir geri çağırmayı kaldırmanıza olanak tanıyan removeUpdateListener
işlevi.
THREE.js'de ışın kılıcı
THREE.js, WebGL'nin düşük düzey ayrıntılarını soyutlar ve soruna odaklanmamıza olanak tanır. Sorunumuz Stormtrooper'larla savaşmak. Bir silaha ihtiyacımız var. Şimdi bir ışın kılıcı oluşturalım.
Işın kılıcını eski ışınlardan ayıran şey parlak bıçaktır. kullandığı anlamına gelir. Temel olarak iki kısımdan oluşur: ışın ve ışın hareket ettirilirken görülen iz. Parlak silindir şeklinde inşa ettik ve oyuncu hareket ettikçe onu takip eden dinamik bir patika vardır.
Bıçak
Bıçak iki alt bıçaktan oluşur. Bir iç, bir dış mesele. Her ikisi de kendi malzemelerine sahip THREE.js örgüsüdür.
İç bıçak
İç bıçak için özel gölgelendiricili özel bir malzeme kullandık. Biz iki noktayla oluşturulan bir çizgiyi alıp bu ikisi arasındaki çizgiyi yansıtın görebilirsiniz. Bu düzlem, temel olarak mobil cihazınızla savaşırken kontrol ettiğiniz düzlemdir. Kılıca derinlik ve yön hissi verir.
Yuvarlak parlayan bir nesne hissi yaratmak için düzlemdeki herhangi bir noktanın ana noktaya uzaklığı aşağıdaki gibi A ve B noktasını birleştiren bir çizgi görürsünüz. Noktaya ne kadar yakın o kadar parlak olur.
Aşağıdaki kaynak, yoğunluğu kontrol etmek için vFactor
değerini nasıl hesapladığımızı gösterir
kullanarak köşe gölgesindeki sahneyle uyumlu hale getirmek için
parça gölgelendirici'yi tıklayın.
THREE.LaserShader = {
uniforms: {
"uPointA": {type: "v3", value: new THREE.Vector3(0, -1, 0)},
"uPointB": {type: "v3", value: new THREE.Vector3(0, 1, 0)},
"uColor": {type: "c", value: new THREE.Color(1, 0, 0)},
"uMultiplier": {type: "f", value: 3.0},
"uCoreColor": {type: "c", value: new THREE.Color(1, 1, 1)},
"uCoreOpacity": {type: "f", value: 0.8},
"uLowerBound": {type: "f", value: 0.4},
"uUpperBound": {type: "f", value: 0.8},
"uTransitionPower": {type: "f", value: 2},
"uNearPlaneValue": {type: "f", value: -0.01}
},
vertexShader: [
"uniform vec3 uPointA;",
"uniform vec3 uPointB;",
"uniform float uMultiplier;",
"uniform float uNearPlaneValue;",
"varying float vFactor;",
"float getDistanceFromAB(vec2 a, vec2 b, vec2 p) {",
"vec2 l = b - a;",
"float l2 = dot( l, l );",
"float t = dot( p - a, l ) / l2;",
"if( t < 0.0 ) return distance( p, a );",
"if( t > 1.0 ) return distance( p, b );",
"vec2 projection = a + (l * t);",
"return distance( p, projection );",
"}",
"vec3 getIntersection(vec4 a, vec4 b) {",
"vec3 p = a.xyz;",
"vec3 q = b.xyz;",
"vec3 v = normalize( q - p );",
"float t = ( uNearPlaneValue - p.z ) / v.z;",
"return p + (v * t);",
"}",
"void main() {",
"vec4 a = modelViewMatrix * vec4(uPointA, 1.0);",
"vec4 b = modelViewMatrix * vec4(uPointB, 1.0);",
"if(a.z > uNearPlaneValue) a.xyz = getIntersection(a, b);",
"if(b.z > uNearPlaneValue) b.xyz = getIntersection(a, b);",
"a = projectionMatrix * a; a /= a.w;",
"b = projectionMatrix * b; b /= b.w;",
"vec4 p = projectionMatrix * modelViewMatrix * vec4(position, 1.0);",
"gl_Position = p;",
"p /= p.w;",
"float d = getDistanceFromAB(a.xy, b.xy, p.xy) * gl_Position.z;",
"vFactor = 1.0 - clamp(uMultiplier * d, 0.0, 1.0);",
"}"
].join( "\n" ),
fragmentShader: [
"uniform vec3 uColor;",
"uniform vec3 uCoreColor;",
"uniform float uCoreOpacity;",
"uniform float uLowerBound;",
"uniform float uUpperBound;",
"uniform float uTransitionPower;",
"varying float vFactor;",
"void main() {",
"vec4 col = vec4(uColor, vFactor);",
"float factor = smoothstep(uLowerBound, uUpperBound, vFactor);",
"factor = pow(factor, uTransitionPower);",
"vec4 coreCol = vec4(uCoreColor, uCoreOpacity);",
"vec4 finalCol = mix(col, coreCol, factor);",
"gl_FragColor = finalCol;",
"}"
].join( "\n" )
};
Dış Bıçak Parlaklığı
Dış parlaklık için ayrı bir oluşturma arabelleğine oluşturur ve elde etmek için işleme sonrası çiçek efekti ve son resimle parlaklık sağlayabilir. Aşağıdaki resimde, iyi bir kılıç elde etmek için sahip olmanız gereken üç farklı bölge gösterilmektedir. Yani beyaz çekirdek, ortadaki dış parıltı.
Işın Kılıcı Yolu
Star Wars serisinde görüldüğü gibi, ışın kılıcının izi efektin tam olarak ortaya çıkması için önemlidir. Patikaları, üçgenleri sevenlerle oluşturduk. ışın kılıcının hareketine göre dinamik olarak değişir. Bu hayranlar ve görsel açıdan daha iyi hale getirilmesi için son işlemciye iletilir. To fan geometrisinde bir çizgi segmentimiz var ve önceki dönüşümüne göre ve mevcut dönüşümden sonra örgü içinde yeni bir üçgen oluşturup kuyruk kısmından belirli bir süre sonra.
Bir örgü oluşturduktan sonra ona basit bir malzeme atarız ve son işlemci olarak kullanabilirsiniz. Dış bıçak ışıltısına uyguladığımız aynı parlama efektini kullanırız ve gördüğünüz gibi düzgün bir iz elde ederiz:
Patikanın çevresinde parıltı
Son parçanın tamamlanması için gerçek alanın etrafındaki ışıltıyı pek çok şekilde oluşturulabilir. Bizim çözümümüz ayrıntıya giremezsiniz. Performans nedeniyle, özel bir bir sabitleyici etrafında pürüzsüz bir kenar oluşturan bu arabellek için bir gölgelendirici oluşturucu arabelleğine Ardından bu çıktıyı son oluşturma işleminde birleştiririz. Burada, izi çevreleyen parıltıyı görebilirsiniz:
Sonuç
Polimer, güçlü bir kitaplık ve kavramdır (WebComponents, genel). Onunla ne yapacağınıza siz karar verirsiniz. Basit bir kullanıcı arayüzü düğmesinden tam boyutlu bir WebGL uygulamasına kadar her şey olabilir. Önceki bölümlerde size Polymer'i verimli bir şekilde kullanmanıza yardımcı olacak ve aynı zamanda yüksek performans gösteren daha karmaşık modüllerin olur. Ayrıca, WebGL'de güzel görünen bir ışın kılıcını nasıl elde edebileceğinizi de gösterdik. Tüm bunları bir araya getirirseniz üretim sunucusuna dağıtmadan önce Polymer öğelerinizi Vulcanize etmeyi unutmayın. CSP uyumluluğunuzu korumak istiyorsanız Crisper'ı kullanmayı da unutmayın.