split code and add ui for changing fragment shader
This commit is contained in:
parent
ed902a2ed2
commit
55cb25f291
|
@ -1288,6 +1288,15 @@
|
|||
"@types/range-parser": "*"
|
||||
}
|
||||
},
|
||||
"@types/jquery": {
|
||||
"version": "3.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.4.tgz",
|
||||
"integrity": "sha512-//9CHhaUt/rurMJTxGI+I6DmsNHgYU6d8aSLFfO5dB7+10lwLnaWT0z5GY/yY82Q/M+B+0Qh3TixlJ8vmBeqIw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/sizzle": "*"
|
||||
}
|
||||
},
|
||||
"@types/json-schema": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz",
|
||||
|
@ -1353,6 +1362,12 @@
|
|||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/sizzle": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
|
||||
"integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "4.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.8.1.tgz",
|
||||
|
@ -3694,6 +3709,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"jquery": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz",
|
||||
"integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg=="
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
"@babel/preset-typescript": "^7.12.7",
|
||||
"@babel/runtime-corejs3": "^7.12.5",
|
||||
"@types/express": "^4.17.9",
|
||||
"@types/jquery": "^3.5.4",
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^17.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.8.1",
|
||||
|
@ -63,6 +64,7 @@
|
|||
"ejs": "^3.1.5",
|
||||
"express": "^4.17.1",
|
||||
"gl-mat4": "^1.2.0",
|
||||
"jquery": "^3.5.1",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1"
|
||||
}
|
||||
|
|
|
@ -14,5 +14,10 @@ body {
|
|||
}
|
||||
|
||||
#glCanvas {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#ui {
|
||||
display: inline-block;
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
|
||||
/**
|
||||
* init buffers to create a square
|
||||
* @param {any} gl the web gl context
|
||||
* @param {Array<number>} positions the position buffer to be loaded
|
||||
* @param {Array<number>} indices the index buffer to be loaded
|
||||
* @param {Array<number>} normals the normal buffer to be loaded
|
||||
* @return {any} the buffers
|
||||
*/
|
||||
export function initBuffers(
|
||||
gl: any,
|
||||
positions: Array<number>,
|
||||
indices: Array<number>,
|
||||
normals: Array<number>) {
|
||||
const positionBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||
gl.bufferData(
|
||||
gl.ARRAY_BUFFER,
|
||||
new Float32Array(positions),
|
||||
gl.STATIC_DRAW);
|
||||
|
||||
const normalBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
|
||||
gl.bufferData(
|
||||
gl.ARRAY_BUFFER,
|
||||
new Float32Array(normals),
|
||||
gl.STATIC_DRAW);
|
||||
|
||||
const myColors = [
|
||||
[1.0, 1.0, 1.0, 1.0],
|
||||
[1.0, 0.0, 0.0, 1.0],
|
||||
[0.0, 1.0, 0.0, 1.0],
|
||||
[0.0, 0.0, 1.0, 1.0],
|
||||
[1.0, 1.0, 0.0, 1.0],
|
||||
[1.0, 0.0, 1.0, 1.0],
|
||||
[0.0, 0.0, 0.0, 1.0],
|
||||
[0.0, 1.0, 1.0, 1.0],
|
||||
];
|
||||
|
||||
let faceColors: any = [];
|
||||
|
||||
for (let i = 0; i < 70; i++) {
|
||||
faceColors = faceColors.concat(myColors);
|
||||
}
|
||||
// Convert the array of colors into a table for all the vertices.
|
||||
|
||||
const colors: any = [];
|
||||
|
||||
for (let j = 0; j < indices.length; ++j) {
|
||||
const c = [
|
||||
myColors[Math.floor(Math.random() * 8)],
|
||||
faceColors[Math.floor(Math.random() * 8)],
|
||||
faceColors[Math.floor(Math.random() * 8)],
|
||||
faceColors[Math.floor(Math.random() * 8)],
|
||||
];
|
||||
// Repeat each color four times for the four vertices of the face
|
||||
// colors = colors.concat([1.0, 1.0, 1.0, 1.0]);
|
||||
colors.push(c[0][0]);
|
||||
colors.push(c[0][1]);
|
||||
colors.push(c[0][2]);
|
||||
colors.push(c[0][3]);
|
||||
}
|
||||
|
||||
const colorBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
|
||||
|
||||
const indexBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,
|
||||
new Uint16Array(indices), gl.STATIC_DRAW);
|
||||
// Now send the element array to GL
|
||||
|
||||
return {
|
||||
position: positionBuffer,
|
||||
color: colorBuffer,
|
||||
indices: indexBuffer,
|
||||
normals: normalBuffer,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* init buffers to create a square
|
||||
* @param {any} gl the web gl context
|
||||
* @param {any} buffers the buffers to delete
|
||||
*/
|
||||
export function deleteBuffers(gl: any, buffers: any) {
|
||||
for (const buffer of Object.entries(buffers)) {
|
||||
gl.deleteBuffer(buffer);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
import {initShaderProgram,
|
||||
unlinkShaderProgram} from './shaders';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {any} gl the gl context
|
||||
* @param {any} shaderProgram the shader program
|
||||
* @param {any} fragmentShader the current fragment shader
|
||||
* @param {string} fsSource new fragment shader source
|
||||
* @param {string} vsSource current vsSource
|
||||
* @return {any} the program info object
|
||||
*/
|
||||
export function changeFragmentShader(gl: any,
|
||||
shaderProgram: any,
|
||||
fragmentShader: any,
|
||||
fsSource: string,
|
||||
vsSource: string) {
|
||||
shaderProgram = unlinkShaderProgram(gl,
|
||||
fragmentShader,
|
||||
shaderProgram);
|
||||
[shaderProgram, fragmentShader] = initShaderProgram(gl,
|
||||
vsSource,
|
||||
fsSource)!;
|
||||
const programInfo = {
|
||||
program: shaderProgram,
|
||||
attribLocations: {
|
||||
vertexPosition: gl.getAttribLocation(shaderProgram,
|
||||
'aVertexPosition'),
|
||||
vertexColor: gl.getAttribLocation(shaderProgram,
|
||||
'aVertexColor'),
|
||||
vertexNormal: gl.getAttribLocation(shaderProgram,
|
||||
'aVertexNormal'),
|
||||
},
|
||||
uniformLocations: {
|
||||
projectionMatrix: gl.getUniformLocation(
|
||||
shaderProgram, 'uProjectionMatrix'),
|
||||
viewMatrix: gl.getUniformLocation(
|
||||
shaderProgram, 'uviewMatrix'),
|
||||
modelMatrix: gl.getUniformLocation(
|
||||
shaderProgram, 'umodelMatrix'),
|
||||
},
|
||||
};
|
||||
return programInfo;
|
||||
}
|
|
@ -2,6 +2,11 @@
|
|||
import mat4 from 'gl-mat4';
|
||||
// @ts-ignore
|
||||
import convert from './objparser';
|
||||
import $ from 'jquery';
|
||||
|
||||
import {initBuffers} from './buffers';
|
||||
import {initShaderProgram} from './shaders';
|
||||
import {changeFragmentShader} from './changeshader';
|
||||
|
||||
let squareRotation = 0.0;
|
||||
|
||||
|
@ -83,6 +88,42 @@ function main() {
|
|||
gl_FragColor = vec4((texture * diffuse * 0.9) + (texture * 0.1) + (specular * vec3(1.)), 1.0);
|
||||
}`;
|
||||
|
||||
const fsSource2 = `
|
||||
precision highp float;
|
||||
|
||||
varying highp vec4 vColor;
|
||||
varying highp vec4 vNormal;
|
||||
varying highp vec3 vPosition;
|
||||
|
||||
vec3 extremize(vec3 v, float n) {
|
||||
if (v.x > n / 2.)
|
||||
v.x = n;
|
||||
else
|
||||
v.x = 0.;
|
||||
if (v.y > n / 2.)
|
||||
v.y = n;
|
||||
else
|
||||
v.y = 0.;
|
||||
if (v.z > n / 2.)
|
||||
v.z = n;
|
||||
else
|
||||
v.z = 0.;
|
||||
return v;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 n = normalize(vec3(-500., 1000., 500.) - vPosition);
|
||||
float diffuse = max(dot(vNormal.xyz, n), 0.);
|
||||
float specular = pow(
|
||||
max(dot(
|
||||
reflect(n, vNormal.xyz),
|
||||
normalize(vec3(0., 0., -50.) - vPosition)),
|
||||
0.), 10.);
|
||||
vec3 tmp = extremize(mod(vPosition.xyz + vec3(100.), vec3(3.)), 3.);
|
||||
vec3 texture = vec3(tmp.x / 3., tmp.y / 3., tmp.z / 3.);
|
||||
gl_FragColor = vec4((texture * diffuse * 0.9) + (texture * vec3(0.1)) + (specular * vec3(1.)), 1.0);
|
||||
}`;
|
||||
|
||||
/* eslint-enable */
|
||||
|
||||
fetch('/static/objs/teapot_normals.obj').then((response) => {
|
||||
|
@ -96,8 +137,8 @@ function main() {
|
|||
] = convert(data);
|
||||
console.log(uvs);
|
||||
console.log(squareRotation);
|
||||
const normals = [];
|
||||
const positions = [];
|
||||
const normals: any = [];
|
||||
const positions: any = [];
|
||||
for (let i = 0; i < convertedNormals.length; i++) {
|
||||
if (i % 4 != 0) {
|
||||
normals.push(convertedNormals[i]);
|
||||
|
@ -108,9 +149,11 @@ function main() {
|
|||
positions.push(convertedPositions[i]);
|
||||
}
|
||||
}
|
||||
const shaderProgram = initShaderProgram(gl, vsSource, fsSource);
|
||||
const [shaderProgram, fragmentShader]: any = initShaderProgram(gl,
|
||||
vsSource,
|
||||
fsSource);
|
||||
|
||||
const programInfo: any = {
|
||||
let programInfo: any = {
|
||||
program: shaderProgram,
|
||||
attribLocations: {
|
||||
vertexPosition: gl.getAttribLocation(shaderProgram,
|
||||
|
@ -132,6 +175,7 @@ function main() {
|
|||
|
||||
const buffers = initBuffers(gl, positions, indices, normals);
|
||||
let then = 0;
|
||||
let changed = false;
|
||||
|
||||
/**
|
||||
* Draws the scene repeatedly
|
||||
|
@ -140,142 +184,28 @@ function main() {
|
|||
function render(now: any) {
|
||||
now *= 0.001;
|
||||
const deltaTime = now - then;
|
||||
if (now >= 1 && changed == false) {
|
||||
changed = true;
|
||||
}
|
||||
then = now;
|
||||
drawScene(gl, programInfo, buffers, deltaTime, indices.length);
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$('#button1').on('click', function() {
|
||||
programInfo = changeFragmentShader(gl,
|
||||
shaderProgram, fragmentShader, fsSource, vsSource);
|
||||
});
|
||||
$('#button2').on('click', function() {
|
||||
programInfo = changeFragmentShader(gl,
|
||||
shaderProgram, fragmentShader, fsSource2, vsSource);
|
||||
});
|
||||
});
|
||||
requestAnimationFrame(render);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a shader program, so WebGL knows how to draw our data
|
||||
* @param {any} gl the WebGL context
|
||||
* @param {string} vsSource the vertex shader source
|
||||
* @param {string} fsSource the fragment shader source
|
||||
* @return {any} the shader program
|
||||
*/
|
||||
function initShaderProgram(gl: any, vsSource: string, fsSource: string) {
|
||||
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
|
||||
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
|
||||
|
||||
// Create the shader program
|
||||
const shaderProgram = gl.createProgram();
|
||||
gl.attachShader(shaderProgram, vertexShader);
|
||||
gl.attachShader(shaderProgram, fragmentShader);
|
||||
gl.linkProgram(shaderProgram);
|
||||
|
||||
// If creating the shader program failed, alert
|
||||
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
|
||||
alert('Unable to initialize the shader program: ' +
|
||||
gl.getProgramInfoLog(shaderProgram));
|
||||
return null;
|
||||
}
|
||||
return shaderProgram;
|
||||
}
|
||||
|
||||
/**
|
||||
* load a GL shader
|
||||
* @param {any} gl the WebGL context
|
||||
* @param {any} type type of shader to load
|
||||
* @param {string} source source code of shader
|
||||
* @return {any} the loaded shader
|
||||
*/
|
||||
function loadShader(gl: any, type: any, source: string) {
|
||||
const shader = gl.createShader(type);
|
||||
// Send the source to the shader object
|
||||
gl.shaderSource(shader, source);
|
||||
// Compile the shader program
|
||||
gl.compileShader(shader);
|
||||
// See if it compiled successfully
|
||||
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||
alert('An error occurred compiling the shaders: ' +
|
||||
gl.getShaderInfoLog(shader));
|
||||
gl.deleteShader(shader);
|
||||
return null;
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
/**
|
||||
* init buffers to create a square
|
||||
* @param {any} gl the web gl context
|
||||
* @param {Array<number>} positions the position buffer to be loaded
|
||||
* @param {Array<number>} indices the index buffer to be loaded
|
||||
* @param {Array<number>} normals the normal buffer to be loaded
|
||||
* @return {any} the buffer
|
||||
*/
|
||||
function initBuffers(
|
||||
gl: any,
|
||||
positions: Array<number>,
|
||||
indices: Array<number>,
|
||||
normals: Array<number>) {
|
||||
const positionBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||
gl.bufferData(
|
||||
gl.ARRAY_BUFFER,
|
||||
new Float32Array(positions),
|
||||
gl.STATIC_DRAW);
|
||||
|
||||
const normalBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
|
||||
gl.bufferData(
|
||||
gl.ARRAY_BUFFER,
|
||||
new Float32Array(normals),
|
||||
gl.STATIC_DRAW);
|
||||
|
||||
const myColors = [
|
||||
[1.0, 1.0, 1.0, 1.0],
|
||||
[1.0, 0.0, 0.0, 1.0],
|
||||
[0.0, 1.0, 0.0, 1.0],
|
||||
[0.0, 0.0, 1.0, 1.0],
|
||||
[1.0, 1.0, 0.0, 1.0],
|
||||
[1.0, 0.0, 1.0, 1.0],
|
||||
[0.0, 0.0, 0.0, 1.0],
|
||||
[0.0, 1.0, 1.0, 1.0],
|
||||
];
|
||||
|
||||
let faceColors: any = [];
|
||||
|
||||
for (let i = 0; i < 70; i++) {
|
||||
faceColors = faceColors.concat(myColors);
|
||||
}
|
||||
// Convert the array of colors into a table for all the vertices.
|
||||
|
||||
const colors: any = [];
|
||||
|
||||
for (let j = 0; j < indices.length; ++j) {
|
||||
const c = [
|
||||
myColors[Math.floor(Math.random() * 8)],
|
||||
faceColors[Math.floor(Math.random() * 8)],
|
||||
faceColors[Math.floor(Math.random() * 8)],
|
||||
faceColors[Math.floor(Math.random() * 8)],
|
||||
];
|
||||
// Repeat each color four times for the four vertices of the face
|
||||
// colors = colors.concat([1.0, 1.0, 1.0, 1.0]);
|
||||
colors.push(c[0][0]);
|
||||
colors.push(c[0][1]);
|
||||
colors.push(c[0][2]);
|
||||
colors.push(c[0][3]);
|
||||
}
|
||||
|
||||
const colorBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
|
||||
|
||||
const indexBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,
|
||||
new Uint16Array(indices), gl.STATIC_DRAW);
|
||||
// Now send the element array to GL
|
||||
|
||||
return {
|
||||
position: positionBuffer,
|
||||
color: colorBuffer,
|
||||
indices: indexBuffer,
|
||||
normals: normalBuffer,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a webgl scene
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Initialize a shader program, so WebGL knows how to draw our data
|
||||
* @param {any} gl the WebGL context
|
||||
* @param {any} shader the shader to unlink
|
||||
* @param {any} shaderProgram the existing shaderprogram
|
||||
* @return {any} the shader program
|
||||
*/
|
||||
export function unlinkShaderProgram(gl: any, shader: any, shaderProgram: any) {
|
||||
// Create the shader program
|
||||
gl.detachShader(shaderProgram, shader);
|
||||
gl.deleteShader(shader);
|
||||
return shaderProgram;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a shader program, so WebGL knows how to draw our data
|
||||
* @param {any} gl the WebGL context
|
||||
* @param {string} vsSource the vertex shader source
|
||||
* @param {string} fsSource the fragment shader source
|
||||
* @return {any} the shader program
|
||||
*/
|
||||
export function initShaderProgram(gl: any, vsSource: string, fsSource: string) {
|
||||
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
|
||||
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
|
||||
|
||||
// Create the shader program
|
||||
const shaderProgram = gl.createProgram();
|
||||
gl.attachShader(shaderProgram, vertexShader);
|
||||
gl.attachShader(shaderProgram, fragmentShader);
|
||||
gl.linkProgram(shaderProgram);
|
||||
|
||||
// If creating the shader program failed, alert
|
||||
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
|
||||
alert('Unable to initialize the shader program: ' +
|
||||
gl.getProgramInfoLog(shaderProgram));
|
||||
return null;
|
||||
}
|
||||
return [shaderProgram, fragmentShader];
|
||||
}
|
||||
|
||||
/**
|
||||
* load a GL shader
|
||||
* @param {any} gl the WebGL context
|
||||
* @param {any} type type of shader to load
|
||||
* @param {string} source source code of shader
|
||||
* @return {any} the loaded shader
|
||||
*/
|
||||
export function loadShader(gl: any, type: any, source: string) {
|
||||
const shader = gl.createShader(type);
|
||||
// Send the source to the shader object
|
||||
gl.shaderSource(shader, source);
|
||||
// Compile the shader program
|
||||
gl.compileShader(shader);
|
||||
// See if it compiled successfully
|
||||
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||
alert('An error occurred compiling the shaders: ' +
|
||||
gl.getShaderInfoLog(shader));
|
||||
gl.deleteShader(shader);
|
||||
return null;
|
||||
}
|
||||
return shader;
|
||||
}
|
|
@ -13,6 +13,10 @@
|
|||
<body>
|
||||
<div id="root">
|
||||
<canvas id='glCanvas' width='640' height='640'></canvas>
|
||||
<div id='ui'>
|
||||
<button id='button1'>Change Shader to black and white</button>
|
||||
<button id='button2'>Change Shader to colored</button>
|
||||
</div>
|
||||
</div>
|
||||
<script src="js/bundle.js"></script>
|
||||
</body>
|
||||
|
|
Loading…
Reference in New Issue