webgl html5 编辑器,在线WebGL顶点和片段着色器代码编辑器

JavaScript

语言:

JaveScriptBabelCoffeeScript

确定

var CANVAS_WIDTH = 640;

var CANVAS_HEIGHT = 480;

var TIME_DIVIDER = 10000;

var NUMBER_OF_PARTICLES = 120000;

var SPAWN_MIN = 0.;

var SPAWN_IN_CIRCLE = false;

var BLEND_ADDITIVE = true;

var DEPTH_TEST = false;

var BACKGROUND_COLOR = {

red: 0.1,

green: 0.1,

blue: 0.1

};

var gl; //WebGL context

var canvasElement;

var codeElement;

var editingVertexShader = true;

var pointBuffer; //array buffer for particle points

var timeUniform; //uniform location for Time

var shaderProgram, vertexShader, fragmentShader;

var startTime;

//on page load

window.onload = function() {

codeElement = document.getElementById("code");

canvasElement = document.getElementById("display");

canvasElement.width = CANVAS_WIDTH;

canvasElement.height = CANVAS_HEIGHT;

gl = canvasElement.getContext("webgl");

if (!gl) {

gl = canvasElement.getContext("experimental-webgl"); // if getting the context for 'webgl' fails try and get the experimental context

if (!gl) {

alert("WebGL is not supported in this browser!");

return;

}

}

//Particle vertex positions

var particleSpawnPoints = new Float32Array(2 * NUMBER_OF_PARTICLES);

//Iterate through particles spawning random positions from -1 to 1

var i = NUMBER_OF_PARTICLES;

if (SPAWN_IN_CIRCLE) {

while (i--) {

var spawnAng = Math.random() * Math.PI * 2.;

var spawnDist = Math.random();

while (spawnDist < SPAWN_MIN) spawnDist = Math.random();

var particleIndex = i * 2;

particleSpawnPoints[particleIndex++] = Math.sin(spawnAng) * spawnDist; //Put generated spawn position in flow array

particleSpawnPoints[particleIndex] = Math.cos(spawnAng) * spawnDist;

}

} else {

while (i--) {

var spawnX = Math.random() * 2 - 1;

while (spawnX * spawnX < SPAWN_MIN) spawnX = Math.random() * 2 - 1;

var spawnY = Math.random() * 2 - 1;

while (spawnY * spawnY < SPAWN_MIN) spawnY = Math.random() * 2 - 1;

var particleIndex = i * 2;

particleSpawnPoints[particleIndex++] = spawnX; //Put generated spawn position in flow array

particleSpawnPoints[particleIndex] = spawnY;

}

}

//Create array buffer

pointBuffer = gl.createBuffer();

gl.bindBuffer(gl.ARRAY_BUFFER, pointBuffer);

gl.bufferData(gl.ARRAY_BUFFER, particleSpawnPoints, gl.STATIC_DRAW); //Move float array of spawn points into array buffer

ReloadShader(true);

gl.enable(gl.BLEND);

if (BLEND_ADDITIVE) {

gl.blendFunc(gl.SRC_ALPHA, gl.ONE);

} else {

gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

}

if (DEPTH_TEST) {

gl.enable(gl.DEPTH_TEST);

} else {

gl.disable(gl.DEPTH_TEST);

}

gl.clearColor(BACKGROUND_COLOR.red, BACKGROUND_COLOR.green, BACKGROUND_COLOR.blue, 1);

startTime = Date.now();

render();

};

function render() {

requestAnimationFrame(render);

gl.clear(gl.COLOR_BUFFER_BIT);

gl.uniform1f(timeUniform, (Date.now() - startTime) / TIME_DIVIDER);

gl.drawArrays(gl.POINTS, 0, NUMBER_OF_PARTICLES);

}

function SaveChanges() {

if (editingVertexShader) {

window.localStorage.vertexCode = codeElement.value;

} else {

window.localStorage.fragmentCode = codeElement.value;

}

}

function ReloadShader(first) {

if (!first) {

//Free shaders

gl.deleteProgram(shaderProgram);

gl.deleteShader(vertexShader);

gl.deleteShader(fragmentShader);

SaveChanges();

} else {

//Set default vertex/fragment shader code if there isn't any saved code

if (!window.localStorage.vertexCode) {

window.localStorage.vertexCode = ENCIRCLINGSYSTEM_VERTEX;

}

if (!window.localStorage.fragmentCode) {

window.localStorage.fragmentCode = ENCIRCLINGSYSTEM_FRAGMENT;

}

if (editingVertexShader) {

codeElement.value = window.localStorage.vertexCode;

} else {

codeElement.value = window.localStorage.fragmentCode;

}

}

vertexShader = gl.createShader(gl.VERTEX_SHADER);

gl.shaderSource(vertexShader, window.localStorage.vertexCode);

gl.compileShader(vertexShader);

if (!debugShader(vertexShader)) alert("Error in vertex shader! Check the developer console of your browser for a detailed error description.");

fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

gl.shaderSource(fragmentShader, window.localStorage.fragmentCode);

gl.compileShader(fragmentShader);

if (!debugShader(fragmentShader)) alert("Error in fragment shader! Check the developer console of your browser for a detailed error description.");

shaderProgram = gl.createProgram();

gl.attachShader(shaderProgram, vertexShader);

gl.attachShader(shaderProgram, fragmentShader);

gl.linkProgram(shaderProgram);

gl.useProgram(shaderProgram);

var vertAttrib = gl.getAttribLocation(shaderProgram, "Vertex");

gl.enableVertexAttribArray(vertAttrib);

gl.vertexAttribPointer(pointBuffer, 2, gl.FLOAT, false, 4, 0);

timeUniform = gl.getUniformLocation(shaderProgram, "Time");

}

function debugShader(shader) {

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {

console.log(gl.getShaderInfoLog(shader));

return false;

}

return true;

}

function SwitchShaderCode() {

SaveChanges();

codeElement.value = editingVertexShader ? window.localStorage.fragmentCode : window.localStorage.vertexCode;

document.getElementById("switchBtn").value = editingVertexShader ? "Switch to vertex shader" : "Switch to fragment shader";

editingVertexShader = !editingVertexShader;

}

function SimplestPreset() {

window.localStorage.vertexCode = SIMPLESYSTEM_VERTEX;

window.localStorage.fragmentCode = SIMPLESYSTEM_FRAGMENT;

codeElement.value = !editingVertexShader ? window.localStorage.fragmentCode : window.localStorage.vertexCode;

ReloadShader(false);

}

function EncirclingPreset() {

window.localStorage.vertexCode = ENCIRCLINGSYSTEM_VERTEX;

window.localStorage.fragmentCode = ENCIRCLINGSYSTEM_FRAGMENT;

codeElement.value = !editingVertexShader ? window.localStorage.fragmentCode : window.localStorage.vertexCode;

ReloadShader(false);

}

function FlagPreset() {

window.localStorage.vertexCode = FLAGSYSTEM_VERTEX;

window.localStorage.fragmentCode = FLAGSYSTEM_FRAGMENT;

codeElement.value = !editingVertexShader ? window.localStorage.fragmentCode : window.localStorage.vertexCode;

ReloadShader(false);

}

function Export() {

var qt = '"';

var displayId = "psysdisplayed" + Math.floor(Math.random() * 100000);

var styleStr = "html, body {color: white; text-align: center; background-color: rgb(" + Math.floor(BACKGROUND_COLOR.red * 255) + "," + Math.floor(BACKGROUND_COLOR.green * 255) + "," + Math.floor(BACKGROUND_COLOR.blue * 255) + ")}";

var headStr = "Made using Ethan Shulmans particle vertex/fragment shader editor";

var htmlStr = "var width = " + CANVAS_WIDTH + "; var height = " + CANVAS_HEIGHT + "; var vbuf; var pstart; var nump; var canvasElement; var gl; window.onload = function() { canvasElement = document.getElementById(" + qt + displayId + qt + "); canvasElement.width = width; canvasElement.height = height; gl = canvasElement.getContext(" + qt + "webgl" + qt + "); if (!gl) { gl = canvasElement.getContext(" + qt + "experimental-webgl" + qt + "); if (!gl) { alert(" + qt + "WebGL not supported!" + qt + ");}} nump = " + NUMBER_OF_PARTICLES + "; pstart = new Float32Array(nump*2); var i = nump; while (i--) {var ai =i*2;";

if (SPAWN_IN_CIRCLE) {

htmlStr += "var spawnAng = Math.random()*Math.PI*2.; var spawnDist = Math.random(); while (spawnDist < " + SPAWN_MIN + ") {spawnDist = Math.random();} var ai = i*2; pstart[ai++] = Math.sin(spawnAng)*spawnDist; pstart[ai] = Math.cos(spawnAng)*spawnDist; }";

} else {

htmlStr += "var ai = i*2; var bf = Math.random(); while (bf*bf < " + SPAWN_MIN + ") {bf = Math.random();} pstart[ai++] = bf; bf = Math.random(); while(bf*bf < " + SPAWN_MIN + ") {bf = Math.random();} pstart[ai] = bf; }";

}

var vertPlaced = window.localStorage.vertexCode.replace(/(\r\n|\n|\r)/gm, " ");

var fragPlaces = window.localStorage.fragmentCode.replace(/(\r\n|\n|\r)/gm, " ");

htmlStr += "vbuf = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER,vbuf); gl.bufferData(gl.ARRAY_BUFFER,pstart,gl.STATIC_DRAW); var vsh = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vsh, " + qt + vertPlaced + qt + "); gl.compileShader(vsh); var fsh = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fsh," + qt + fragPlaces + qt + "); gl.compileShader(fsh); var program = gl.createProgram(); gl.attachShader(program,vsh); gl.attachShader(program,fsh); gl.linkProgram(program); gl.useProgram(program); var vattr = gl.getAttribLocation(program," + qt + "Vertex" + qt + "); gl.enableVertexAttribArray(vattr); gl.vertexAttribPointer(vbuf,2,gl.FLOAT,false,4,0); tuni = gl.getUniformLocation(program," + qt + "Time" + qt + "); gl.enable(gl.BLEND);";

if (BLEND_ADDITIVE) {

htmlStr += "gl.blendFunc(gl.SRC_ALPHA,gl.ONE);";

} else {

htmlStr += "gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA);";

}

if (DEPTH_TEST) {

htmlStr += " gl.enable(gl.DEPTH_TEST);";

} else {

htmlStr += "gl.disable(gl.DEPTH_TEST);";

}

htmlStr += "gl.clearColor(" + BACKGROUND_COLOR.red + "," + BACKGROUND_COLOR.green + "," + BACKGROUND_COLOR.blue + ",1); startTime = Date.now(); render(); }; var tuni,startTime; function render() { gl.clear(gl.COLOR_BUFFER_BIT); gl.uniform1f(tuni,(Date.now()-startTime)/" + TIME_DIVIDER + "); gl.drawArrays(gl.POINTS,0,nump); window.requestAnimationFrame(render); }";

var myWindow = window.open("", "Export Window", "width=400, height=300");

myWindow.document.body.appendChild(document.createTextNode("HTML = " + headStr));

myWindow.document.body.appendChild(document.createElement("hr"));

myWindow.document.body.appendChild(document.createTextNode("CSS = " + styleStr));

myWindow.document.body.appendChild(document.createElement("hr"));

myWindow.document.body.appendChild(document.createTextNode("JAVASCRIPT = "));

myWindow.document.body.appendChild(document.createTextNode(htmlStr));

}

var SIMPLESYSTEM_VERTEX = "precision mediump float;\n\n" +

"attribute vec2 Vertex;\n" +

"uniform float Time;\n\n" +

"void main() {\n" +

"gl_PointSize = 1.;\n" +

"gl_Position = vec4(Vertex*mod(Time,1.),0.,1.);\n" +

"}";

var SIMPLESYSTEM_FRAGMENT = "precision mediump float;\n\n" +

"void main() {\n" +

"gl_FragColor = vec4(1.,1.,1.,.1);\n" +

"}";

var ENCIRCLINGSYSTEM_VERTEX = "precision mediump float;\n\n" +

"attribute vec2 Vertex;\nuniform float Time;\n" +

"void main() {\n" +

"gl_PointSize = 2.5;\n\n" +

"vec2 v = (Vertex*.4- Vertex*(mod(Time+length(Vertex),1.)))*vec2(cos(Time),1.);\n" +

"float ct = (cos(v.x*30.+Time*5.)+cos(v.y*30.+Time*20.));\n" +

"v = mat2(cos(v.x*(1.+ct)),-sin(v.x*(1.+ct)),sin(v.y*(32.+ct)),cos(v.y*(32.+ct)))*v;\n\n" +

"gl_Position=vec4(v,0.,1.);\n" +

"}";

var ENCIRCLINGSYSTEM_FRAGMENT = "\nprecision mediump float;\n\n" +

"void main() {\n" +

"gl_FragColor = vec4(1.,.6,.6,.1);\n}";

var FLAGSYSTEM_VERTEX = "\nprecision mediump float;\n\n" +

"attribute vec2 Vertex;\n varying vec2 V;\n uniform float Time;\n\n" +

"void main(void) {\n" +

"gl_PointSize = 2.;\nV = Vertex;\n\n float pt = (mod(Time+length(Vertex)*.1+.9,.65));\n float ang = atan(Vertex.y,Vertex.x);\n" +

"vec2 v = (Vertex+vec2(sin(ang),cos(ang))*pt)*pt*(cos(ang*30.)*.5*max(0.,pt-.2)*16.+1.);\n" +

"float ct = (pt*4.);\n" +

"v = mat2(sin(ct),cos(ct),cos(ct),-sin(ct))*v;\n\n" +

"gl_Position=vec4(v,0.,1.);\n" +

"}";

var FLAGSYSTEM_FRAGMENT = "\nprecision mediump float;\n\n varying vec2 V;\n uniform float Time;\n\n" +

"void main(void) {\n\n" +

"gl_FragColor = mix(mix(vec4(1.,1.,1.,.05),vec4(1.,0.,0.,.05),floor(mod(V.y+1.175,.325)*6.)),vec4(.2,.2,1.,.05),clamp(1.-length(max(abs(V+vec2(.7,.7))-vec2(.3),0.))/.01, 0., 1.));\n\n}";

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值