Skip to content

Instantly share code, notes, and snippets.

@sfpgmr
Last active October 23, 2016 09:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sfpgmr/573aae74c3ac996e799e to your computer and use it in GitHub Desktop.
Save sfpgmr/573aae74c3ac996e799e to your computer and use it in GitHub Desktop.
WebGL 0002 回転するタイトル

About

WebGLとThree.jsを使用した自己学習用のサンプルです。

<!DOCTYPE html>
<html>
<head>
<title>WebGL Test</title>
<meta name="keywords" content="WebGL,HTML5,three.js" />
<meta name="description" content="WebGL,HTML5,three.js" />
<meta charset="UTF-8">
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://www.sfpgmr.net/scripts/three/three.js"></script>
<script src="http://www.sfpgmr.net/scripts/three/Detector.js"></script>
<script src="http://www.sfpgmr.net/scripts/three/stats.min.js"></script>
<script type="text/javascript" id="code">
//
var textureRoot = 'http://www.sfpgmr.net/test/webgl/data/';
var textureLength = 0;
var textureCount = 0;
var textureFiles = new Array(0);
//var imageLoaded = false;
//var ctx;
// キー入力
var keyCheck = { up: false, down: false, left: false, right: false, z: false };
var keyBuffer = Array(0);
function TextureFile(src,array) {
this.src = src;
this.array = array;
this.loadComplete = false;
this.loadError = false;
var self = this;
this.texture = THREE.ImageUtils.loadTexture(textureRoot + this.src, {},
function (texture) {
self.loadComplete = true;
if (self.src.match(/\.png/i)) {
self.texture.premultiplyAlpha = true;
}
self.array.loadCompletedCount++;
}
,
function()
{
self.loadError = true;
}
);
return this;
}
// ImageFile.prototype.load = function () { this.image.src = imageRoot + this.src; };
// タスク管理コンストラクタ
function Tasks() {
this.array = new Array(0);
this.needSort = false;
return this;
}
Tasks.prototype = {
// indexの位置のタスクを置き換える
setNextTask: function (index, func, priority) {
if (priority == undefined) {
priority = 10000;
}
func.priority = priority;
this.array[index] = func;
this.needSort = true;
},
pushTask: function (func, priority) {
if (priority == undefined) {
priority = 10000;
}
func.priority = priority;
for (var i = 0; i < this.length; ++i) {
if (this.array[i] == null) {
this.array[i] = func;
return;
}
}
this.array.push(func);
this.needSort = true;
},
// 配列を取得する
getArray: function () {
return this.array;
},
// タスクをクリアする
clear: function () {
this.array.length = 0;
},
// ソートが必要かチェックし、ソートする
checkSort: function () {
if (this.needSort) {
this.array.sort(function (a, b) { return a.priority > b.priority; });
needSort = false;
}
}
};
var tasks = new Tasks();
var CONSOLE_WIDTH = 480.0;
var CONSOLE_HEIGHT = 640.0;
var VIRTUAL_WIDTH = CONSOLE_WIDTH / 2.0;
var VIRTUAL_HEIGHT = CONSOLE_HEIGHT / 2.0;
var SPRITE_SIZE_X = 16.0;
var SPRITE_SIZE_Y = 16.0;
var renderer;
var stats;
var scene;
var camera;
var mesh;
var author;
$(window).ready(function () {
$('#Start')[0].disabled = true;
textureFiles = {
loadCompletedCount:0,
font: (new TextureFile('Font.png', textureFiles)),
font1: (new TextureFile('Font2.png', textureFiles)),
author: (new TextureFile('author.png', textureFiles))/*,
myship: new ImageFile('myship.png')*/
};
// WebGLのサポートチェック
if (!Detector.webgl) {
//Detector.addGetWebGLMessage({ parent: $("#content")[0] });
$('#content').text('お使いのブラウザではWebGLはサポートしていないようです。');
return;
}
$('#source-code').text($('html').html());
// レンダラーの作成
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(CONSOLE_WIDTH, CONSOLE_HEIGHT);
renderer.setClearColorHex(0x000000, 1);
renderer.domElement.id = 'console';
renderer.domElement.className = 'console';
renderer.domElement.style.zIndex = 0;
$('#content').append(renderer.domElement);
// Stats オブジェクト(FPS表示)の作成表示
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
$('#content').append(stats.domElement);
stats.domElement.style.left = renderer.domElement.clientWidth - stats.domElement.clientWidth + 'px';
//2D描画コンテキストの表示
/* ctx = $('#info-display').css('z-index', 2);
ctx = $('#info-display')[0].getContext('2d');
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.font = "12px 'MS ゴシック'";*/
// シーンの作成
scene = new THREE.Scene();
// カメラの作成
camera = new THREE.PerspectiveCamera(90.0, CONSOLE_WIDTH / CONSOLE_HEIGHT);
camera.position = new THREE.Vector3(0, 0, 240.0 * CONSOLE_HEIGHT / CONSOLE_WIDTH);
camera.lookAt(new THREE.Vector3(0, 0, 0));
//var camera = new THREE.Camera();
//camera.position.z = 1.0;
// ライトの作成
//var light = new THREE.DirectionalLight(0xffffff);
//light.position = new THREE.Vector3(0.577, 0.577, 0.577);
//scene.add(light);
//var ambient = new THREE.AmbientLight(0xffffff);
//scene.add(ambient);
// レンダリング
var baseTime = +new Date;
var d = -0.2;
var start = false;
function game() {
if (start) {
requestAnimationFrame(game);
}
// タスクの呼び出し
// メインに描画
try {
tasks.checkSort();
$.each(tasks.getArray(), function (taskIndex) {
if (this != null) {
this(taskIndex);
}
}
);
} catch (e) {
ExitError(e);
}
};
renderer.clear();
// エラーで終了する。
function ExitError(e) {
//ctx.fillStyle = "red";
//ctx.fillRect(0, 0, CONSOLE_WIDTH, CONSOLE_HEIGHT);
//ctx.fillStyle = "white";
//ctx.fillText("Error : " + e, 0, 20);
////alert(e);
start = false;
throw e;
}
// 開始・停止ボタンの設定 //
$('#Start').click(function () {
if (!start) {
start = true;
$('#Start').text('Stop');
tasks.clear();
tasks.pushTask(init);
tasks.pushTask(render);
game();
} else {
start = false;
$('#Start').text('Start');
}
});
// ソースコード表示ボタンの設定 //
$('#Show-Code').click(function () {
var code = $('#source-code');
if (code.css('display') == 'none') {
code.css('display', 'block');
$('#Show-Code').text('ソース非表示');
} else {
code.css('display', 'none');
$('#Show-Code').text('ソース表示');
}
});
// キー入力処理 //
$(document).keydown(function (e) {
if (keyBuffer.length > 16) {
keyBuffer.shift();
}
keyBuffer.push(e.keyCode);
switch (e.keyCode) {
case 37:
keyCheck.left = true;
break;
case 38:
keyCheck.up = true;
break;
case 39:
keyCheck.right = true;
break;
case 40:
keyCheck.down = true;
break;
case 90:
keyCheck.z = true;
break;
}
});
$(document).keyup(function (e) {
switch (e.keyCode) {
case 37:
keyCheck.left = false;
break;
case 38:
keyCheck.up = false;
break;
case 39:
keyCheck.right = false;
break;
case 40:
keyCheck.down = false;
break;
case 90:
keyCheck.z = false;
break;
}
});
// 表示エリアの調整 //
$('#content').height($('#console').height());
$('#content').width($('#console').width());
/* $('#info-display').height($('#console').height());
$('#info-display').width($('#console').width());*/
$('#source-code').width($('#content').width());
$('#source-code').height($('#content').height());
$('#source-code').css('top', $('#navigation').height() + 'px');
// 初期化タスク //
function render(taskIndex) {
renderer.render(scene, camera);
stats.update();
}
function init(taskIndex) {
scene = new THREE.Scene();
// 物体を作成
{
var canvas = $('<canvas>')[0];
//$('body').append(canvas);
var w = textureFiles.author.texture.image.width;
var h = textureFiles.author.texture.image.height;
canvas.width = w;
canvas.height = h;
var ctx = canvas.getContext('2d');
ctx.drawImage(textureFiles.author.texture.image, 0, 0);
var data = ctx.getImageData(0, 0, w, h);
var geometry = new THREE.Geometry();
geometry.vert_start = [];
geometry.vert_end = [];
{
var i = 0;
for (var y = 0; y < h; ++y) {
for (var x = 0; x < w; ++x) {
var color = new THREE.Color();
var r = data.data[i++];
var g = data.data[i++];
var b = data.data[i++];
var a = data.data[i++];
if (a != 0) {
color.setRGB(r / 255.0, g / 255.0, b / 255.0);
var vert = new THREE.Vector3(((x - w / 2.0)) * 2.0, ((y - h / 2)) * -2.0, 0.0);
var vert2 = new THREE.Vector3(1200 * Math.random() - 600, 1200 * Math.random() - 600, 1200 * Math.random() - 600);
geometry.vert_start.push(new THREE.Vector3(vert2.x - vert.x,vert2.y - vert.y,vert2.z - vert.z));
geometry.vertices.push(vert2);
geometry.vert_end.push(vert);
geometry.colors.push(color);
}
}
}
}
// マテリアルを作成
//var texture = THREE.ImageUtils.loadTexture('images/particle1.png');
var material = new THREE.ParticleBasicMaterial({
size: 2 , blending: THREE.NormalBlending,
transparent: true, vertexColors: true, depthTest: false//, map: texture
});
author = new THREE.ParticleSystem(geometry, material);
author.position = new THREE.Vector3(0.0, 0.0, 0.0);
author.geometry.vertices.length;
//mesh.sortParticles = false;
//var mesh1 = new THREE.ParticleSystem();
//mesh.scale.x = mesh.scale.y = 8.0;
//var material = new THREE.MeshBasicMaterial({ map: textureFiles.author.texture });
////material.shading = THREE.FlatShading;
////material.antialias = false;
//material.transparent = true;
//author = new THREE.Mesh(
// new THREE.PlaneGeometry(textureFiles.author.texture.image.width , textureFiles.author.texture.image.height ),
// material
// );
//author.scale.x = author.scale.y = 2.0;
scene.add(author);
}
tasks.setNextTask(taskIndex, printAuthor());
}
// 作者表示
function printAuthor() {
var step = 0;
var count = 1.0;
var wait = 60;
var proc_count = 0;
keyBuffer.length = 0;
return function (taskIndex) {
// 何かキー入力があった場合は次のタスクへ
//if (keyBuffer.length > 0) {
// keyBuffer.length = 0;
// step = 4;
//}
switch (step) {
// フェード・イン
case 0:
if (count <= 0.01) {
count -= 0.0005;
} else {
count -= 0.0025;
}
if (count < 0.0) {
author.rotation.x = author.rotation.y = author.rotation.z = 0.0;
var end = author.geometry.vertices.length;
for (var i = 0; i < end; ++i) {
author.geometry.vertices[i].x = author.geometry.vert_end[i].x;
author.geometry.vertices[i].y = author.geometry.vert_end[i].y;
author.geometry.vertices[i].z = author.geometry.vert_end[i].z;
}
author.geometry.verticesNeedUpdate = true;
step++;
} else {
var end = author.geometry.vertices.length;
var v = author.geometry.vertices;
var d = author.geometry.vert_start;
var v2 = author.geometry.vert_end;
for (var i = 0; i < end; ++i) {
v[i].x = v2[i].x + d[i].x * count;
v[i].y = v2[i].y + d[i].y * count;
v[i].z = v2[i].z + d[i].z * count;
}
author.geometry.verticesNeedUpdate = true;
author.rotation.x = author.rotation.y = author.rotation.z = count * 4.0;
author.material.opacity = 1.0;
}
break;
// 待ち
case 1:
if (! --wait) step++;
break;
//フェードアウト
case 2:
count += 0.05;
author.material.opacity = 1.0 - count;
if (count >= 1.0) {
count = 1.0;
wait = 60;
step++;
}
break;
// 少し待ち
case 3:
if (! --wait) {
step = 0;
wait = 60;
//step++;
}
break;
// 次のタスクへ
case 4:
{
scene.remove(author);
// 表示する物体の作成
// 形状データを作成
var color = {
'0': new THREE.Color(0x000000),
'1': new THREE.Color(0x0000FF),
'2': new THREE.Color(0x00FF00),
'3': new THREE.Color(0x00FFFF),
'4': new THREE.Color(0xFF0000),
'5': new THREE.Color(0xFF00FF),
'6': new THREE.Color(0xFFFF00),
'7': new THREE.Color(0xFFFFFF),
'8': new THREE.Color(0x000000),
'9': new THREE.Color(0x000080),
'A': new THREE.Color(0x008000),
'B': new THREE.Color(0x008080),
'C': new THREE.Color(0x800000),
'D': new THREE.Color(0x800080),
'E': new THREE.Color(0x808000),
'F': new THREE.Color(0x808080)
}
var enemy =
"0000777777770000" +
"0007777777777000" +
"0777777777777770" +
"7777777777777777" +
"7770000770000777" +
"7770000770000777" +
"7777777777777777" +
"0777777777777770" +
"0077777777777700" +
"0007777777777000" +
"0077777777777700" +
"0777777777777770" +
"7777777007777777" +
"7777770000777777" +
"7777700000077777" +
"0777000000007770";
var my_ship =
"00000007F0000000" +
"00000007F0000000" +
"00000077FF000000" +
"0000007198000000" +
"000000711F000000" +
"0000077198800000" +
"000007719F800000" +
"0000077778800000" +
"00007777FF870000" +
"0007777778877000" +
"07777777FF877770" +
"77777777F8877777" +
"77777777F8887777" +
"77777777F8887777" +
"000077F008880000" +
"000044C004C80000";
//var tex = THREE.ImageUtils.loadTexture('test.png');
//{
var geometry = new THREE.Geometry();
var i = 0;
for (var y = 0; y < SPRITE_SIZE_Y; ++y) {
for (var x = 0; x < SPRITE_SIZE_X; ++x) {
var pixel = my_ship.charAt(i++);
if (pixel != '0') {
geometry.vertices.push(new THREE.Vector3(((x - SPRITE_SIZE_X / 2.0)) * 2.0, ((y - SPRITE_SIZE_Y / 2)) * -2.0, 0.0));
// geometry.vertices.push(new THREE.Vector3((x - SPRITE_SIZE_X / 2) * 2 , -(y - SPRITE_SIZE_Y / 2) * 2 , 0.0));
geometry.colors.push(color[pixel]);
}
}
}
// マテリアルを作成
//var texture = THREE.ImageUtils.loadTexture('images/particle1.png');
var material = new THREE.ParticleBasicMaterial({
size: 2 * 8.0, blending: THREE.NoBlending,
transparent: true, vertexColors: true, depthTest: false//, map: texture
});
mesh = new THREE.ParticleSystem(geometry, material);
mesh.position = new THREE.Vector3(-0.0, -0.0, 0.0);
mesh.sortParticles = false;
//var mesh1 = new THREE.ParticleSystem();
mesh.scale.x = mesh.scale.y = 8.0;
//ctx.clearRect(0, 0, CONSOLE_WIDTH, CONSOLE_HEIGHT);
scene.add(mesh);
tasks.setNextTask(taskIndex, myship_action);
}
break;
}
//ctx.fillStyle = "rgba(127,127,0,1.0)";
//ctx.fillRect(0, 0, CONSOLE_WIDTH, CONSOLE_HEIGHT);
//var backup = ctx.globalAlpha;
//ctx.globalAlpha = count;
//ctx.drawImage(imageFiles.font.image, (CONSOLE_WIDTH - imageFiles.font.image.width) / 2, (CONSOLE_HEIGHT - imageFiles.font.image.height) / 2);
//ctx.globalAlpha = backup;
};
}
function myship_action(taskIndex) {
var t = (+new Date - baseTime) / 1000;
mesh.rotation.z = t * 0.5;
}
$('#Start')[0].disabled = false;
});
</script>
<style type="text/css">
.content {
width: 640px;
position: relative;
margin-left: auto;
margin-right: auto;
margin-top: 0;
margin-bottom: 0;
padding: 0;
border: 0;
}
.navigation {
position: relative;
display: block;
vertical-align: top;
margin-top: 2px;
margin-bottom: 2px;
}
body {
padding: 0;
border: 0;
margin: 0;
}
nav > button {
width: 100px;
height: 45px;
border: 2px solid rgba(255,0,0,1.0);
padding: 2px;
margin: 2px;
color: rgba(255,0,0,1.0);
background: rgba(0,0,0,0);
}
nav > button:hover {
border-color: rgba(255,0,0,1.0);
color: rgba(255,0,0,1.0);
background: rgba(255,0,0,0.55);
}
.source-code {
position: absolute;
display: none;
left: 0;
padding-top: 0px;
margin: 0px;
border: 0px;
overflow-y: auto;
overflow-wrap: break-word;
background: rgba(0,0,0,0.5);
color: white;
font-size: 10px;
}
.console {
margin: 0;
padding: 0;
border: 0;
}
.header {
position: relative;
height: 50px;
}
.info-display{
position:absolute;
}
</style>
</head>
<body>
<div id="content" class="content">
<header class="header">
<nav id="navigation" class="navigation">
<button id="Start" title="クリックすると開始・停止">Start</button>
<button id="Show-Code" title="ソースコードの表示">ソース表示</button>
</nav>
</header>
<pre id="source-code" class="source-code">
</pre>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment