texture support
This commit is contained in:
parent
b1168ca920
commit
ce7914732e
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
Binary file not shown.
After Width: | Height: | Size: 718 KiB |
|
@ -5,13 +5,15 @@
|
|||
* @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
|
||||
* @param {Array<number>} uvs the texture buffer to be loaded
|
||||
* @return {any} the buffers
|
||||
*/
|
||||
export function initBuffers(
|
||||
gl: any,
|
||||
positions: Array<number>,
|
||||
indices: Array<number>,
|
||||
normals: Array<number>) {
|
||||
normals: Array<number>,
|
||||
uvs: Array<number>) {
|
||||
const positionBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||
gl.bufferData(
|
||||
|
@ -32,10 +34,17 @@ export function initBuffers(
|
|||
new Uint16Array(indices), gl.STATIC_DRAW);
|
||||
// Now send the element array to GL
|
||||
|
||||
const uvBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER,
|
||||
new Float32Array(uvs),
|
||||
gl.STATIC_DRAW);
|
||||
|
||||
return {
|
||||
position: positionBuffer,
|
||||
positions: positionBuffer,
|
||||
indices: indexBuffer,
|
||||
normals: normalBuffer,
|
||||
uvs: uvBuffer,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -45,8 +54,8 @@ export function initBuffers(
|
|||
* @param {any} buffers the buffers to delete
|
||||
*/
|
||||
export function deleteBuffers(gl: any, buffers: any) {
|
||||
gl.deleteBuffer(buffers.color);
|
||||
gl.deleteBuffer(buffers.position);
|
||||
gl.deleteBuffer(buffers.uvs);
|
||||
gl.deleteBuffer(buffers.positions);
|
||||
gl.deleteBuffer(buffers.normals);
|
||||
gl.deleteBuffer(buffers.indices);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ export function changeFragmentShader(gl: any,
|
|||
'aVertexColor'),
|
||||
vertexNormal: gl.getAttribLocation(shaderProgram,
|
||||
'aVertexNormal'),
|
||||
textureCoord: gl.getAttribLocation(shaderProgram,
|
||||
'aTextureCoord'),
|
||||
},
|
||||
uniformLocations: {
|
||||
projectionMatrix: gl.getUniformLocation(
|
||||
|
@ -38,6 +40,8 @@ export function changeFragmentShader(gl: any,
|
|||
shaderProgram, 'uviewMatrix'),
|
||||
modelMatrix: gl.getUniformLocation(
|
||||
shaderProgram, 'umodelMatrix'),
|
||||
uSampler: gl.getUniformLocation(
|
||||
shaderProgram, 'uSampler'),
|
||||
},
|
||||
};
|
||||
return [programInfo, fragmentShader];
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
// @ts-ignore
|
||||
import mat4 from 'gl-mat4';
|
||||
// @ts-ignore
|
||||
import convert from './objparser';
|
||||
import {convert} from './objparser';
|
||||
import $ from 'jquery';
|
||||
|
||||
import {initBuffers, deleteBuffers} from './buffers';
|
||||
import {initShaderProgram} from './shaders';
|
||||
import {changeFragmentShader} from './changeshader';
|
||||
import {loadTexture} from './texture';
|
||||
|
||||
let squareRotation = 0.0;
|
||||
|
||||
|
@ -31,6 +32,7 @@ async function main() {
|
|||
const vsSource = `
|
||||
attribute vec4 aVertexPosition;
|
||||
attribute vec4 aVertexNormal;
|
||||
attribute vec2 aTextureCoord;
|
||||
|
||||
uniform mat4 uProjectionMatrix;
|
||||
uniform mat4 uviewMatrix;
|
||||
|
@ -38,6 +40,8 @@ async function main() {
|
|||
|
||||
varying highp vec4 vNormal;
|
||||
varying highp vec3 vPosition;
|
||||
varying highp vec2 vTextureCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = uProjectionMatrix *
|
||||
|
@ -46,6 +50,7 @@ async function main() {
|
|||
aVertexPosition;
|
||||
vPosition = vec3(aVertexPosition);
|
||||
vNormal = umodelMatrix * aVertexNormal;
|
||||
vTextureCoord = aTextureCoord;
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -152,6 +157,27 @@ async function main() {
|
|||
gl_FragColor = vec4((diffuse * 0.8) + (vec3(0.2)) + (specular * vec3(1.)), 1.0);
|
||||
}`;
|
||||
|
||||
const fsSource4 = `
|
||||
precision highp float;
|
||||
|
||||
varying highp vec2 vTextureCoord;
|
||||
|
||||
varying highp vec4 vNormal;
|
||||
varying highp vec3 vPosition;
|
||||
uniform sampler2D uSampler;
|
||||
|
||||
void main() {
|
||||
highp vec4 texelColor = texture2D(uSampler, vTextureCoord);
|
||||
vec3 n = normalize(vec3(-50000., 100000., 50000.) - vPosition);
|
||||
float diffuse = max(dot(normalize(vNormal.xyz), n), 0.);
|
||||
float specular = pow(
|
||||
max(dot(
|
||||
reflect(n, normalize(vNormal.xyz)),
|
||||
normalize(vec3(0., 0., -50.) - vPosition)),
|
||||
0.), 10.);
|
||||
gl_FragColor = vec4((texelColor.xyz * diffuse * 0.8) + (texelColor.xyz * vec3(0.2)) + (specular * vec3(1.)), 1.0);
|
||||
}`;
|
||||
|
||||
/* eslint-enable */
|
||||
|
||||
/**
|
||||
|
@ -165,7 +191,7 @@ async function main() {
|
|||
return data;
|
||||
}
|
||||
|
||||
const data = await getObj('/static/objs/teapot.obj');
|
||||
const data = await getObj('/static/objs/fox.obj');
|
||||
let distance: any = $('#input1').val();
|
||||
let circleSize: any = $('#input2').val();
|
||||
distance = parseFloat(distance);
|
||||
|
@ -177,10 +203,9 @@ async function main() {
|
|||
indices,
|
||||
] = convert(data);
|
||||
let length = indices.length;
|
||||
console.log(uvs);
|
||||
let [shaderProgram, fragmentShader]: any = initShaderProgram(gl,
|
||||
vsSource,
|
||||
fsSource3);
|
||||
fsSource4);
|
||||
|
||||
let programInfo: any = {
|
||||
program: shaderProgram,
|
||||
|
@ -189,6 +214,8 @@ async function main() {
|
|||
'aVertexPosition'),
|
||||
vertexNormal: gl.getAttribLocation(shaderProgram,
|
||||
'aVertexNormal'),
|
||||
textureCoord: gl.getAttribLocation(shaderProgram,
|
||||
'aTextureCoord'),
|
||||
},
|
||||
uniformLocations: {
|
||||
projectionMatrix: gl.getUniformLocation(
|
||||
|
@ -197,10 +224,13 @@ async function main() {
|
|||
shaderProgram, 'uviewMatrix'),
|
||||
modelMatrix: gl.getUniformLocation(
|
||||
shaderProgram, 'umodelMatrix'),
|
||||
uSampler: gl.getUniformLocation(
|
||||
shaderProgram, 'uSampler'),
|
||||
},
|
||||
};
|
||||
|
||||
let buffers = initBuffers(gl, positions, indices, normals);
|
||||
let texture = loadTexture(gl, '/static/textures/fox.png');
|
||||
let buffers = initBuffers(gl, positions, indices, normals, uvs);
|
||||
let then = 0;
|
||||
let changed = false;
|
||||
|
||||
|
@ -221,7 +251,8 @@ async function main() {
|
|||
deltaTime,
|
||||
length,
|
||||
distance,
|
||||
circleSize);
|
||||
circleSize,
|
||||
texture);
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
|
@ -236,10 +267,9 @@ async function main() {
|
|||
uvs,
|
||||
indices,
|
||||
] = convert(data);
|
||||
console.log(uvs);
|
||||
length = indices.length;
|
||||
deleteBuffers(gl, buffers);
|
||||
buffers = initBuffers(gl, positions, indices, normals);
|
||||
buffers = initBuffers(gl, positions, indices, normals, uvs);
|
||||
}
|
||||
|
||||
$(function() {
|
||||
|
@ -255,18 +285,22 @@ async function main() {
|
|||
$('#changecirclesize').click();
|
||||
}
|
||||
});
|
||||
$('#button1').on('click', function() {
|
||||
$('#s_blackandwhite').on('click', function() {
|
||||
[programInfo, fragmentShader] = changeFragmentShader(gl,
|
||||
shaderProgram, fragmentShader, fsSource, vsSource);
|
||||
});
|
||||
$('#button2').on('click', function() {
|
||||
$('#s_color').on('click', function() {
|
||||
[programInfo, fragmentShader] = changeFragmentShader(gl,
|
||||
shaderProgram, fragmentShader, fsSource2, vsSource);
|
||||
});
|
||||
$('#button3').on('click', function() {
|
||||
$('#s_flat').on('click', function() {
|
||||
[programInfo, fragmentShader] = changeFragmentShader(gl,
|
||||
shaderProgram, fragmentShader, fsSource3, vsSource);
|
||||
});
|
||||
$('#s_texture').on('click', function() {
|
||||
[programInfo, fragmentShader] = changeFragmentShader(gl,
|
||||
shaderProgram, fragmentShader, fsSource4, vsSource);
|
||||
});
|
||||
$('#changedistance').on('click', function() {
|
||||
distance = $('#input1').val();
|
||||
distance = parseFloat(distance);
|
||||
|
@ -287,6 +321,18 @@ async function main() {
|
|||
const data = await getObj('/static/objs/fox.obj');
|
||||
updateObj(data);
|
||||
});
|
||||
$('#t_wall').on('click', async function() {
|
||||
texture = loadTexture(gl, '/static/textures/wall.png');
|
||||
});
|
||||
$('#t_ice').on('click', async function() {
|
||||
texture = loadTexture(gl, '/static/textures/ice.png');
|
||||
});
|
||||
$('#t_noise').on('click', async function() {
|
||||
texture = loadTexture(gl, '/static/textures/noise.png');
|
||||
});
|
||||
$('#t_fox').on('click', async function() {
|
||||
texture = loadTexture(gl, '/static/textures/fox.png');
|
||||
});
|
||||
});
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
|
@ -300,6 +346,7 @@ async function main() {
|
|||
* @param {number} length the index buffer length
|
||||
* @param {number} distance distance of camera
|
||||
* @param {number} circleSize size of circle the object is rotating around
|
||||
* @param {any} texture the texture to load
|
||||
*/
|
||||
function drawScene(gl: any,
|
||||
programInfo: any,
|
||||
|
@ -307,7 +354,8 @@ function drawScene(gl: any,
|
|||
deltaTime: number,
|
||||
length: number,
|
||||
distance: number,
|
||||
circleSize: number) {
|
||||
circleSize: number,
|
||||
texture: any) {
|
||||
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
||||
gl.clearDepth(1.0);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
|
@ -374,7 +422,7 @@ function drawScene(gl: any,
|
|||
const normalize = false;
|
||||
const stride = 0;
|
||||
const offset = 0;
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.positions);
|
||||
gl.vertexAttribPointer(
|
||||
programInfo.attribLocations.vertexPosition,
|
||||
numComponents,
|
||||
|
@ -405,6 +453,30 @@ function drawScene(gl: any,
|
|||
programInfo.attribLocations.vertexNormal);
|
||||
}
|
||||
|
||||
// tell webgl how to pull out the texture coordinates from buffer
|
||||
{
|
||||
const num = 2; // every coordinate composed of 2 values
|
||||
const type = gl.FLOAT; // the data in the buffer is 32 bit float
|
||||
const normalize = false; // don't normalize
|
||||
const stride = 0; // how many bytes to get from one set to the next
|
||||
const offset = 0; // how many bytes inside the buffer to start from
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.uvs);
|
||||
gl.vertexAttribPointer(programInfo.attribLocations.textureCoord,
|
||||
num,
|
||||
type,
|
||||
normalize,
|
||||
stride,
|
||||
offset);
|
||||
gl.enableVertexAttribArray(programInfo.attribLocations.textureCoord);
|
||||
}
|
||||
|
||||
// Tell WebGL we want to affect texture unit 0
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
// Bind the texture to texture unit 0
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
// Tell the shader we bound the texture to texture unit 0
|
||||
gl.uniform1i(programInfo.uniformLocations.uSampler, 0);
|
||||
|
||||
// Tell WebGL which indices to use to index the vertices
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffers.indices);
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
export default function convert (objText) {
|
||||
export function convert (objText) {
|
||||
const lines = objText.split("\n");
|
||||
|
||||
let smoothing = false;
|
||||
|
||||
const positions = [];
|
||||
|
@ -11,16 +10,14 @@ export default function convert (objText) {
|
|||
const indices = [];
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (lines[i] != '')
|
||||
{
|
||||
const rawchunks = lines[i].split(" ").map(x => x.trim());
|
||||
const line = lines[i];
|
||||
const rawchunks = line.split(" ").map(x => x.trim());
|
||||
const chunks = [];
|
||||
for (let i = 0; i < rawchunks.length; i++) {
|
||||
if (rawchunks[i] != '') {
|
||||
chunks.push(rawchunks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
switch (chunks[0]) {
|
||||
case "v": {
|
||||
positions.push(chunks.splice(1).map(parseFloat));
|
||||
|
@ -49,6 +46,7 @@ export default function convert (objText) {
|
|||
const c2 = (smoothing ? "s" : "") + chunks[2];
|
||||
const c3 = (smoothing ? "s" : "") + chunks[3];
|
||||
|
||||
|
||||
let index1 = vertices.indexOf(c1);
|
||||
if (index1 === -1) {
|
||||
index1 = vertices.length;
|
||||
|
@ -72,6 +70,27 @@ export default function convert (objText) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
const avgNormals = [];
|
||||
for (let i = 0; i < vertices.length; i++) {
|
||||
if (vertices[i].startsWith("s")) {
|
||||
const d = vertices[i].substr(1).split("/");
|
||||
const normal = normals[d[2] - 1];
|
||||
const index = d[0] - 1;
|
||||
|
||||
if (avgNormals[index]) {
|
||||
avgNormals[index][0] += normal[0];
|
||||
avgNormals[index][1] += normal[1];
|
||||
avgNormals[index][2] += normal[2];
|
||||
} else {
|
||||
avgNormals[index] = normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let n of avgNormals) {
|
||||
const len = Math.hypot(...n);
|
||||
avgNormals[avgNormals.indexOf(n)] = n.map(x => x / len);
|
||||
}
|
||||
|
||||
const outPositions = [];
|
||||
|
@ -82,12 +101,16 @@ export default function convert (objText) {
|
|||
const d = (vertices[i].startsWith("s") ? vertices[i].substr(1) : vertices[i]).split("/");
|
||||
|
||||
outPositions.push(...positions[d[0] - 1]);
|
||||
if (normals.length) {
|
||||
|
||||
if (vertices[i].startsWith("s")) {
|
||||
outNormals.push(...avgNormals[d[0] - 1]);
|
||||
} else {
|
||||
outNormals.push(...normals[d[2] - 1]);
|
||||
}
|
||||
if (uvs.length) {
|
||||
outUVs.push(...uvs[d[1] - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(indices);
|
||||
|
||||
return [outPositions, outNormals, outUVs, indices];
|
||||
};
|
|
@ -15,18 +15,18 @@
|
|||
<canvas id='glCanvas' width='640' height='640'></canvas>
|
||||
<div id='ui'>
|
||||
<div class='ui-block'>
|
||||
<button id='button1'>Change Shader to black and white</button>
|
||||
<button id='button2'>Change Shader to colored</button>
|
||||
<button id='button3'>Change Shader to flat</button>
|
||||
<button id='button3'>Change Shader to texture</button>
|
||||
<button id='s_blackandwhite'>Change Shader to black and white</button>
|
||||
<button id='s_color'>Change Shader to colored</button>
|
||||
<button id='s_flat'>Change Shader to flat</button>
|
||||
<button id='s_texture'>Change Shader to texture</button>
|
||||
</div>
|
||||
<div class='ui-block'>
|
||||
<input id='input1' value='50'></input>
|
||||
<input id='input1' value='250'></input>
|
||||
<button id='changedistance'>Change camera distance</button>
|
||||
<div style='display: inline'>Max distance is 1000</div>
|
||||
</div>
|
||||
<div class='ui-block'>
|
||||
<input id='input2' value='5'></input>
|
||||
<input id='input2' value='30'></input>
|
||||
<button id='changecirclesize'>Change circle size</button>
|
||||
</div>
|
||||
<div class='ui-block'>
|
||||
|
@ -35,10 +35,10 @@
|
|||
<button id='o_fox'>Set object to fox</button>
|
||||
</div>
|
||||
<div class='ui-block'>
|
||||
<button id='t_grey'>Set texture to white</button>
|
||||
<button id='t_wall'>Set texture to wall</button>
|
||||
<button id='t_fox'>Set texture to fox</button>
|
||||
<button id='t_ice'>Set texture to ice</button>
|
||||
<button id='t_noise'>Set texture to noise</button>
|
||||
<button id='t_fox'>Set texture to fox</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue