diff --git a/src/client/init.ts b/src/client/init.ts index 9385f39..861cd82 100644 --- a/src/client/init.ts +++ b/src/client/init.ts @@ -100,30 +100,31 @@ export async function initCache(context: any) { * Set the program info * @param {any} context the program context */ -export function setProgramInfo(context: any) { - context.programInfo = { - program: context.shaderProgram, +export function setProgramInfo(context: any, + shaderProgram: any) { + return { + program: shaderProgram, attribLocations: { - vertexPosition: context.gl.getAttribLocation(context.shaderProgram, + vertexPosition: context.gl.getAttribLocation(shaderProgram, 'aVertexPosition'), - vertexNormal: context.gl.getAttribLocation(context.shaderProgram, + vertexNormal: context.gl.getAttribLocation(shaderProgram, 'aVertexNormal'), - textureCoord: context.gl.getAttribLocation(context.shaderProgram, + textureCoord: context.gl.getAttribLocation(shaderProgram, 'aTextureCoord'), }, uniformLocations: { projectionMatrix: context.gl.getUniformLocation( - context.shaderProgram, 'uProjectionMatrix'), + shaderProgram, 'uProjectionMatrix'), viewMatrix: context.gl.getUniformLocation( - context.shaderProgram, 'uviewMatrix'), + shaderProgram, 'uviewMatrix'), modelMatrix: context.gl.getUniformLocation( - context.shaderProgram, 'umodelMatrix'), + shaderProgram, 'umodelMatrix'), normalMatrix: context.gl.getUniformLocation( - context.shaderProgram, 'unormalMatrix'), + shaderProgram, 'unormalMatrix'), uSampler: context.gl.getUniformLocation( - context.shaderProgram, 'uSampler'), + shaderProgram, 'uSampler'), time: context.gl.getUniformLocation( - context.shaderProgram, 'time'), + shaderProgram, 'time'), }, }; } diff --git a/src/client/main.ts b/src/client/main.ts index cf3296a..d7da37e 100644 --- a/src/client/main.ts +++ b/src/client/main.ts @@ -29,8 +29,10 @@ async function main() { buffers: null, programInfo: null, shaderProgram: null, - fragmentShader: null, - vertexShader: null, + shaders: { + frag: null, + vert: null, + }, cache: null, scene: [], }; @@ -46,9 +48,9 @@ async function main() { initParams(context); await initCache(context); - loadObjBuffers(context, context.cache.objs.racer); - initShaderProgram(context, vsSource, texture); - setProgramInfo(context); + context.buffers = loadObjBuffers(context, context.buffers, context.cache.objs.racer); + [context.shaderProgram, context.shaders.vert, context.shaders.frag] = initShaderProgram(context, context.shaderProgram, context.shaders.frag, context.shaders.vert, vsSource, texture); + context.programInfo = setProgramInfo(context, context.shaderProgram); // context.texture = loadTexture(context.gl, '/static/textures/racer.png'); let then = 0; let changed = false; diff --git a/src/client/objutils.ts b/src/client/objutils.ts index d2e9e8d..e702381 100644 --- a/src/client/objutils.ts +++ b/src/client/objutils.ts @@ -34,9 +34,10 @@ export function pushBuffersToScene( */ export function loadObjBuffers( context: any, + buffers: any, obj: any) { - if (context.buffers != null) { - deleteBuffers(context.gl, context.buffers); + if (buffers != null) { + deleteBuffers(context.gl, buffers); } context.obj = { positions: obj.positions, @@ -44,7 +45,7 @@ export function loadObjBuffers( normals: obj.normals, uvs: obj.uvs, }; - context.buffers = initBuffers(context.gl, + return initBuffers(context.gl, obj.positions, obj.indices, obj.normals, obj.uvs); } diff --git a/src/client/shaders.ts b/src/client/shaders.ts index 6fbca1b..4cd76c4 100644 --- a/src/client/shaders.ts +++ b/src/client/shaders.ts @@ -7,26 +7,30 @@ import {setProgramInfo} from './init'; * @param {string} fsSource the fragment shader source */ export function initShaderProgram(context: any, + shaderProgram: any, + fragmentShader: any, + vertexShader: any, vsSource: string, fsSource: string) { - context.vertexShader = loadShader(context.gl, + vertexShader = loadShader(context.gl, context.gl.VERTEX_SHADER, vsSource); - context.fragmentShader = loadShader(context.gl, + fragmentShader = loadShader(context.gl, context.gl.FRAGMENT_SHADER, fsSource); // Create the shader program - context.shaderProgram = context.gl.createProgram(); - context.gl.attachShader(context.shaderProgram, context.vertexShader); - context.gl.attachShader(context.shaderProgram, context.fragmentShader); - context.gl.linkProgram(context.shaderProgram); + shaderProgram = context.gl.createProgram(); + context.gl.attachShader(shaderProgram, vertexShader); + context.gl.attachShader(shaderProgram, fragmentShader); + context.gl.linkProgram(shaderProgram); // If creating the shader program failed, alert - if (!context.gl.getProgramParameter(context.shaderProgram, + if (!context.gl.getProgramParameter(shaderProgram, context.gl.LINK_STATUS)) { alert('Unable to initialize the shader program: ' + - context.gl.getProgramInfoLog(context.shaderProgram)); - context.shaderProgram = null; + context.gl.getProgramInfoLog(shaderProgram)); + shaderProgram = null; } + return [shaderProgram, vertexShader, fragmentShader]; } /** @@ -59,9 +63,14 @@ export function loadShader(gl: any, type: any, source: string) { * @param {string} vsSource current vsSource */ export function changeFragmentShader(context: any, + programInfo: any, + shaderProgram: any, + fragmentShader: any, + vertexShader: any, fsSource: string, vsSource: string) { - context.gl.deleteShader(context.fragmentShader); - initShaderProgram(context, vsSource, fsSource); - setProgramInfo(context); + context.gl.deleteShader(fragmentShader); + [shaderProgram, vertexShader, fragmentShader] = initShaderProgram(context, shaderProgram, fragmentShader, vertexShader, vsSource, fsSource); + programInfo = setProgramInfo(context, shaderProgram); + return [programInfo, shaderProgram, vertexShader, fragmentShader]; } diff --git a/src/client/uijquery.ts b/src/client/uijquery.ts index 668560c..b0d120a 100644 --- a/src/client/uijquery.ts +++ b/src/client/uijquery.ts @@ -29,8 +29,269 @@ export function uiUpdateScene(context: any) { params: _.cloneDeep(context.params), programInfo: _.cloneDeep(context.programInfo), shaderProgram: _.cloneDeep(context.shaderProgram), - fragmentShader: _.cloneDeep(context.fragmentShader), - vertexShader: _.cloneDeep(context.vertexShader), + shaders: _.cloneDeep(context.shaders), + }); + let instanceRadioString; + if ($('input[name=instance]:checked', '#instanceoptions').val() == + 'normal') { + instanceRadioString = ` + + + + + `; + } else if ( + ($('input[name=instance]:checked', '#instanceoptions').val() == + 'one')) { + instanceRadioString = ` + + + + + `; + } else { + instanceRadioString = ` + + + + + `; + } + $('.scene-block').append(` +
+
Change shader:
+ + + + + + +
+
+
Change instances number:
+ +
+
+
` + instanceRadioString + `
+
+
+
Change rotation:
+
X:
+ +
Y:
+ +
Z:
+ +
+
+
Change scale:
+
X:
+ +
Y:
+ +
Z:
+ +
+
+
Translate:
+
X:
+ +
Y:
+ +
Z:
+ +
+
+
Change object:
+ + + + + +
+
+
Change texture:
+ + + + + + +
`); + $('#' + context.scene.length + 't_wall').on('click', (event) => { + const n = parseInt(event.target.id.split('t')[0]); + if (context.cache.textures.wall == null) { + context.cache.textures.wall = loadTexture(context.gl, + '/static/textures/wall.png'); + } + context.scene[n - 1].texture = context.cache.textures.wall; + }); + $('#' + context.scene.length + 't_ice').on('click', (event) => { + const n = parseInt(event.target.id.split('t')[0]); + if (context.cache.textures.ice == null) { + context.cache.textures.ice = loadTexture(context.gl, + '/static/textures/ice.png'); + } + context.scene[n - 1].texture = context.cache.textures.ice; + }); + $('#' + context.scene.length + 't_fox').on('click', (event) => { + const n = parseInt(event.target.id.split('t')[0]); + if (context.cache.textures.fox == null) { + context.cache.textures.fox = loadTexture(context.gl, + '/static/textures/fox.png'); + } + context.scene[n - 1].texture = context.cache.textures.fox; + }); + $('#' + context.scene.length + 't_racer').on('click', (event) => { + const n = parseInt(event.target.id.split('t')[0]); + if (context.cache.textures.racer == null) { + context.cache.textures.racer = loadTexture(context.gl, + '/static/textures/racer.png'); + } + context.scene[n - 1].texture = context.cache.textures.racer; + }); + $('#' + context.scene.length + 't_racer_wireframe').on('click', + (event) => { + const n = parseInt(event.target.id.split('t')[0]); + if (context.cache.textures.racerWireframe == null) { + context.cache.textures.racerWireframe = loadTexture( + context.gl, + '/static/textures/racer_wireframe.png'); + } + context.scene[n - 1].texture = context.cache.textures.racerWireframe; + }); + $('#' + context.scene.length + 'instanceoptions input').on('change', (event) => { + const n = parseInt(event.target.attributes[2].nodeValue!.split('instance')[0]); + if ($('input[name=' + n + 'instance]:checked', '#' + n + 'instanceoptions').val() == + 'normal') { + context.scene[n - 1].params.instanceNumber = parseFloat($('#' + n + 'instance').val()); + } else if ( + ($('input[name=' + n + 'instance]:checked', '#' + n + 'instanceoptions').val() == + 'one')) { + context.scene[n - 1].params.instanceNumber = 1; + } else { + context.scene[n - 1].params.instanceNumber = 0; + } + }); + $('#' + context.scene.length + 'instance').on('input', (event) => { + const n = parseInt(event.target.id.split('instance')[0]); + if ($('input[name=' + n + 'instance]:checked', '#' + n + 'instanceoptions').val() == + 'normal') { + context.scene[n - 1].params.instanceNumber = parseFloat($('#' + n + 'instance').val()); + } + }); + $('#' + context.scene.length + 'rotx').on('input', (event) => { + const n = parseInt(event.target.id.split('rot')[0]); + console.log(n); + context.scene[n - 1].params.rot.x = parseFloat($('#' + n + 'rotx').val()); + }); + $('#' + context.scene.length + 'roty').on('input', (event) => { + const n = parseInt(event.target.id.split('rot')[0]); + context.scene[n - 1].params.rot.y = parseFloat($('#' + n + 'roty').val()); + }); + $('#' + context.scene.length + 'rotz').on('input', (event) => { + const n = parseInt(event.target.id.split('rot')[0]); + context.scene[n - 1].params.rot.z = parseFloat($('#' + n + 'rotz').val()); + }); + $('#' + context.scene.length + 'posx').on('input', (event) => { + const n = parseInt(event.target.id.split('pos')[0]); + context.scene[n - 1].params.pos.x = parseFloat($('#' + n + 'posx').val()); + }); + $('#' + context.scene.length + 'posy').on('input', (event) => { + const n = parseInt(event.target.id.split('pos')[0]); + context.scene[n - 1].params.pos.y = parseFloat($('#' + n + 'posy').val()); + }); + $('#' + context.scene.length + 'posz').on('input', (event) => { + const n = parseInt(event.target.id.split('pos')[0]); + context.scene[n - 1].params.pos.z = parseFloat($('#' + n + 'posz').val()); + }); + $('#' + context.scene.length + 'scalex').on('input', (event) => { + const n = parseInt(event.target.id.split('scale')[0]); + console.log(n); + console.log(parseFloat($('#' + n + 'scalex').val())); + context.scene[n - 1].params.scale.x = parseFloat($('#' + n + 'scalex').val()); + }); + $('#' + context.scene.length + 'scaley').on('input', (event) => { + const n = parseInt(event.target.id.split('scale')[0]); + context.scene[n - 1].params.scale.y = parseFloat($('#' + n + 'scaley').val()); + }); + $('#' + context.scene.length + 'scalez').on('input', (event) => { + const n = parseInt(event.target.id.split('scale')[0]); + context.scene[n - 1].params.scale.z = parseFloat($('#' + n + 'scalez').val()); + }); + $('#' + context.scene.length + 's_blackandwhite').on('click', function(event) { + const n = parseInt(event.target.id.split('s')[0]); + [context.scene[n - 1].programInfo, context.scene[n - 1].shaderProgram, context.scene[n - 1].shaders.vert, context.scene[n - 1].shaders.frag] = changeFragmentShader(context, context.scene[n - 1].programInfo, context.scene[n - 1].shaderProgram, context.scene[n - 1].shaders.frag, context.scene[n - 1].shaders.vert, blackandwhite, vsSource); + }); + $('#' + context.scene.length + 's_color').on('click', function(event) { + const n = parseInt(event.target.id.split('s')[0]); + [context.scene[n - 1].programInfo, context.scene[n - 1].shaderProgram, context.scene[n - 1].shaders.vert, context.scene[n - 1].shaders.frag] = changeFragmentShader(context, context.scene[n - 1].programInfo, context.scene[n - 1].shaderProgram, context.scene[n - 1].shaders.frag, context.scene[n - 1].shaders.vert, colored, vsSource); + }); + $('#' + context.scene.length + 's_grey').on('click', function(event) { + const n = parseInt(event.target.id.split('s')[0]); + [context.scene[n - 1].programInfo, context.scene[n - 1].shaderProgram, context.scene[n - 1].shaders.vert, context.scene[n - 1].shaders.frag] = changeFragmentShader(context, context.scene[n - 1].programInfo, context.scene[n - 1].shaderProgram, context.scene[n - 1].shaders.frag, context.scene[n - 1].shaders.vert, grey, vsSource); + }); + $('#' + context.scene.length + 's_texture').on('click', function(event) { + const n = parseInt(event.target.id.split('s')[0]); + [context.scene[n - 1].programInfo, context.scene[n - 1].shaderProgram, context.scene[n - 1].shaders.vert, context.scene[n - 1].shaders.frag] = changeFragmentShader(context, context.scene[n - 1].programInfo, context.scene[n - 1].shaderProgram, context.scene[n - 1].shaders.frag, context.scene[n - 1].shaders.vert, texture, vsSource); + }); + $('#' + context.scene.length + 's_sobel').on('click', function(event) { + const n = parseInt(event.target.id.split('s')[0]); + [context.scene[n - 1].programInfo, context.scene[n - 1].shaderProgram, context.scene[n - 1].shaders.vert, context.scene[n - 1].shaders.frag] = changeFragmentShader(context, context.scene[n - 1].programInfo, context.scene[n - 1].shaderProgram, context.scene[n - 1].shaders.frag, context.scene[n - 1].shaders.vert, sobel, vsSource); + }); + $('#' + context.scene.length + 's_fractal').on('click', function(event) { + const n = parseInt(event.target.id.split('s')[0]); + [context.scene[n - 1].programInfo, context.scene[n - 1].shaderProgram, context.scene[n - 1].shaders.vert, context.scene[n - 1].shaders.frag] = changeFragmentShader(context, context.scene[n - 1].programInfo, context.scene[n - 1].shaderProgram, context.scene[n - 1].shaders.frag, context.scene[n - 1].shaders.vert, fractal, vsSource); + }); + $('#' + context.scene.length + 'o_sphere').on('click', async function(event) { + const n = parseInt(event.target.id.split('o')[0]); + if (context.cache.objs.sphere == null) { + const data = await fetchObj('/static/objs/sphere.obj'); + context.cache.objs.sphere = loadObj(data); + } + context.scene[n - 1].buffers = loadObjBuffers(context, context.scene[n - 1].buffers, context.cache.objs.sphere); + context.scene[n - 1].params.len = context.cache.objs.sphere.indices.length; + context.scene[n - 1].params.range = context.cache.objs.sphere.range; + }); + $('#' + context.scene.length + 'o_teapot').on('click', async function(event) { + const n = parseInt(event.target.id.split('o')[0]); + if (context.cache.objs.teapot == null) { + const data = await fetchObj('/static/objs/teapot.obj'); + context.cache.objs.teapot = loadObj(data); + } + context.scene[n - 1].buffers = loadObjBuffers(context, context.scene[n - 1].buffers, context.cache.objs.teapot); + context.scene[n - 1].params.len = context.cache.objs.teapot.indices.length; + context.scene[n - 1].params.range = context.cache.objs.teapot.range; + }); + $('#' + context.scene.length + 'o_fox').on('click', async function(event) { + const n = parseInt(event.target.id.split('o')[0]); + if (context.cache.objs.fox == null) { + const data = await fetchObj('/static/objs/fox.obj'); + context.cache.objs.fox = loadObj(data); + } + context.scene[n - 1].buffers = loadObjBuffers(context, context.scene[n - 1].buffers, context.cache.objs.fox); + context.scene[n - 1].params.len = context.cache.objs.fox.indices.length; + context.scene[n - 1].params.range = context.cache.objs.fox.range; + }); + $('#' + context.scene.length + 'o_mecha').on('click', async function(event) { + const n = parseInt(event.target.id.split('o')[0]); + if (context.cache.objs.mecha == null) { + const data = await fetchObj('/static/objs/mecha.obj'); + context.cache.objs.mecha = loadObj(data); + } + context.scene[n - 1].buffers = loadObjBuffers(context, context.scene[n - 1].buffers, context.cache.objs.mecha); + context.scene[n - 1].params.len = context.cache.objs.mecha.indices.length; + context.scene[n - 1].params.range = context.cache.objs.mecha.range; + }); + $('#' + context.scene.length + 'o_racer').on('click', async function(event) { + const n = parseInt(event.target.id.split('o')[0]); + if (context.cache.objs.racer == null) { + const data = await fetchObj('/static/objs/racer.obj'); + context.cache.objs.racer = loadObj(data); + } + context.scene[n - 1].buffers = loadObjBuffers(context, context.scene[n - 1].buffers, context.cache.objs.racer); + context.scene[n - 1].params.len = context.cache.objs.racer.indices.length; + context.scene[n - 1].params.range = context.cache.objs.racer.range; }); }); } @@ -163,7 +424,7 @@ export function uiUpdateObject(context: any) { const data = await fetchObj('/static/objs/sphere.obj'); context.cache.objs.sphere = loadObj(data); } - loadObjBuffers(context, context.cache.objs.sphere); + context.buffers = loadObjBuffers(context, context.buffers, context.cache.objs.sphere); context.params.len = context.cache.objs.sphere.indices.length; context.params.range = context.cache.objs.sphere.range; }); @@ -172,7 +433,7 @@ export function uiUpdateObject(context: any) { const data = await fetchObj('/static/objs/teapot.obj'); context.cache.objs.teapot = loadObj(data); } - loadObjBuffers(context, context.cache.objs.teapot); + context.buffers = loadObjBuffers(context, context.buffers, context.cache.objs.teapot); context.params.len = context.cache.objs.teapot.indices.length; context.params.range = context.cache.objs.teapot.range; }); @@ -181,7 +442,7 @@ export function uiUpdateObject(context: any) { const data = await fetchObj('/static/objs/fox.obj'); context.cache.objs.fox = loadObj(data); } - loadObjBuffers(context, context.cache.objs.fox); + context.buffers = loadObjBuffers(context, context.buffers, context.cache.objs.fox); context.params.len = context.cache.objs.fox.indices.length; context.params.range = context.cache.objs.fox.range; }); @@ -190,7 +451,7 @@ export function uiUpdateObject(context: any) { const data = await fetchObj('/static/objs/mecha.obj'); context.cache.objs.mecha = loadObj(data); } - loadObjBuffers(context, context.cache.objs.mecha); + context.buffers = loadObjBuffers(context, context.buffers, context.cache.objs.mecha); context.params.len = context.cache.objs.mecha.indices.length; context.params.range = context.cache.objs.mecha.range; }); @@ -199,7 +460,7 @@ export function uiUpdateObject(context: any) { const data = await fetchObj('/static/objs/racer.obj'); context.cache.objs.racer = loadObj(data); } - loadObjBuffers(context, context.cache.objs.racer); + context.buffers = loadObjBuffers(context, context.buffers, context.cache.objs.racer); context.params.len = context.cache.objs.racer.indices.length; context.params.range = context.cache.objs.racer.range; }); @@ -211,21 +472,21 @@ export function uiUpdateObject(context: any) { */ export function uiUpdateShader(context: any) { $('#s_blackandwhite').on('click', function() { - changeFragmentShader(context, blackandwhite, vsSource); + [context.programInfo, context.shaderProgram, context.shaders.vert, context.shaders.frag] = changeFragmentShader(context, context.programInfo, context.shaderProgram, context.shaders.frag, context.shaders.vert, blackandwhite, vsSource); }); $('#s_color').on('click', function() { - changeFragmentShader(context, colored, vsSource); + [context.programInfo, context.shaderProgram, context.shaders.vert, context.shaders.frag] = changeFragmentShader(context, context.programInfo, context.shaderProgram, context.shaders.frag, context.shaders.vert, colored, vsSource); }); $('#s_grey').on('click', function() { - changeFragmentShader(context, grey, vsSource); + [context.programInfo, context.shaderProgram, context.shaders.vert, context.shaders.frag] = changeFragmentShader(context, context.programInfo, context.shaderProgram, context.shaders.frag, context.shaders.vert, grey, vsSource); }); $('#s_texture').on('click', function() { - changeFragmentShader(context, texture, vsSource); + [context.programInfo, context.shaderProgram, context.shaders.vert, context.shaders.frag] = changeFragmentShader(context, context.programInfo, context.shaderProgram, context.shaders.frag, context.shaders.vert, texture, vsSource); }); $('#s_sobel').on('click', function() { - changeFragmentShader(context, sobel, vsSource); + [context.programInfo, context.shaderProgram, context.shaders.vert, context.shaders.frag] = changeFragmentShader(context, context.programInfo, context.shaderProgram, context.shaders.frag, context.shaders.vert, sobel, vsSource); }); $('#s_fractal').on('click', function() { - changeFragmentShader(context, fractal, vsSource); + [context.programInfo, context.shaderProgram, context.shaders.vert, context.shaders.frag] = changeFragmentShader(context, context.programInfo, context.shaderProgram, context.shaders.frag, context.shaders.vert, fractal, vsSource); }); } diff --git a/views/index.ejs b/views/index.ejs index f54038f..efbd019 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -107,6 +107,8 @@
+
+