index.html
<!doctype html>
<html>
<head>
<style>
canvas {
border: 1px solid #000000;
}
</style>
</head>
<body>
<p>
<b>scale value:</b>
<input id="scalex" type="range" min="-2" max="2" value="1" step="0.1" oninput="gl_draw()" />
<b id="scalevaluex">0</b>
<input id="scaley" type="range" min="-2" max="2" value="1" step="0.1" oninput="gl_draw()" />
<b id="scalevaluey">0</b>
</p>
<p>
<b>offset value:</b>
<input id="offsetx" type="range" min="-1" max="1" value="0" step="0.1" oninput="gl_draw()" />
<b id="offsetvaluex">0</b>
<input id="offsety" type="range" min="-1" max="1" value="0" step="0.1" oninput="gl_draw()" />
<b id="offsetvaluey">0</b>
</p>
<p>
<b>rotate value:</b>
<input id="rotate" type="range" min="0" max="6.28" value="0" step="0.01" oninput="gl_draw()" />
<b id="rotatevalue">0</b>
</p>
<p>
<b>cat value:</b>
<input id="cat" type="range" min="0" max="1" value="0" step="0.1" oninput="gl_draw()" />
<b id="catvalue">0</b>
</p>
<canvas id="tri" width="600" height="600" style="width:300px; height:300px">
</canvas>
<script id="vertex_shader" type="myshader">
precision mediump int;
precision mediump float;
uniform mat3 u_all;
attribute vec2 a_PointVertex;
attribute vec2 a_PointUV;
varying vec2 uv;
void main() {
vec3 coord = u_all * vec3(a_PointVertex, 1.0);
gl_Position = vec4(coord.x, coord.y, 0.0, 1.0);
uv = a_PointUV;
uv.y = 1.0 - uv.y;
}
</script>
<script id="fragment_shader" type="myshader">
precision mediump int;
precision mediump float;
uniform sampler2D u_funny_cat;
uniform sampler2D u_eye;
uniform float u_t;
varying vec2 uv;
void main() {
vec4 sample_color_cat = texture2D(u_funny_cat, uv);
vec4 sample_color_eye = texture2D(u_eye, sample_color_cat.xy);
gl_FragColor = vec4(sample_color_cat.xyz * u_t + (1.0 - u_t) * sample_color_eye.xyz, 1.0);
}
</script>
<script type="text/javascript" src="logic.js"></script>
</body>
</html>
logic.js
var pointCanvas = null
var gl = null
var data = null
var dataArr = null
var pointCount = null
var u_all_loc = null
var u_EyeLocation = null
var u_FunnyCatLocation = null
var u_t = null
var scaleDomX = null
var scaleValueDomX = null
var scaleDomY = null
var scaleValueDomY = null
var offsetDomX = null
var offsetValueDomX = null
var offsetDomY = null
var offsetValueDomY = null
var rotateDom = null
var rotateValueDom = null
var catDom = null
var catValueDom = null
// 入口函数
function Main() {
gl_init()
CreateTextureAndLoadImage()
}
function genMat3ForGL(a, b, alpha, A, B) {
let mat3 = [
a * Math.cos(alpha), a * Math.sin(alpha), 0,
-b * Math.sin(alpha), b * Math.cos(alpha), 0,
A, B, 1,
]
return new Float32Array(mat3)
}
function gl_init() {
pointCanvas = document.getElementById('tri')
gl = pointCanvas.getContext('webgl', { preserveDrawingBuffer: true })
data = [-1, -1, 0, 0,
1, -1, 1, 0,
0, 1, 0.5, 1
]
dataArr = new Float32Array(data)
pointCount = 3
buffer_point = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer_point)
gl.bufferData(gl.ARRAY_BUFFER, dataArr, gl.STATIC_DRAW)
//
var vertex_shader_code = document.getElementById('vertex_shader').textContent
var vertex_shader = gl.createShader(gl.VERTEX_SHADER)
gl.shaderSource(vertex_shader, vertex_shader_code)
gl.compileShader(vertex_shader)
// 检查shader错误
const v_compiled = gl.getShaderParameter(vertex_shader, gl.COMPILE_STATUS)
if (!v_compiled) {
const v_theError = gl.getShaderInfoLog(vertex_shader)
console.error(v_theError)
gl.deleteShader(vertex_shader)
}
//
var fragment_shader_code = document.getElementById('fragment_shader').textContent
var fragment_shader = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(fragment_shader, fragment_shader_code)
gl.compileShader(fragment_shader)
// 检查shader错误
const f_compiled = gl.getShaderParameter(fragment_shader, gl.COMPILE_STATUS)
if (!f_compiled) {
const f_theError = gl.getShaderInfoLog(fragment_shader)
console.error(f_theError)
gl.deleteShader(fragment_shader)
}
//
var program = gl.createProgram()
gl.attachShader(program, vertex_shader)
gl.attachShader(program, fragment_shader)
gl.linkProgram(program)
gl.useProgram(program)
// attributes
var a_PointVertex = gl.getAttribLocation(program, 'a_PointVertex')
var a_PointUV = gl.getAttribLocation(program, 'a_PointUV')
gl.vertexAttribPointer(a_PointVertex, 2, gl.FLOAT, false, 16, 0)
gl.enableVertexAttribArray(a_PointVertex)
gl.vertexAttribPointer(a_PointUV, 2, gl.FLOAT, false, 16, 8)
gl.enableVertexAttribArray(a_PointUV)
// uniforms
u_all_loc = gl.getUniformLocation(program, "u_all")
u_t = gl.getUniformLocation(program, "u_t")
u_FunnyCatLocation = gl.getUniformLocation(program, "u_funny_cat")
u_EyeLocation = gl.getUniformLocation(program, "u_eye")
scaleDomX = document.getElementById("scalex")
scaleValueDomX = document.getElementById("scalevaluex")
scaleDomY = document.getElementById("scaley")
scaleValueDomY = document.getElementById("scalevaluey")
offsetDomX = document.getElementById("offsetx")
offsetValueDomX = document.getElementById("offsetvaluex")
offsetDomY = document.getElementById("offsety")
offsetValueDomY = document.getElementById("offsetvaluey")
rotateDom = document.getElementById("rotate")
rotateValueDom = document.getElementById("rotatevalue")
catDom = document.getElementById("cat")
catValueDom = document.getElementById("catvalue")
}
// gl更新逻辑
function gl_draw() {
gl.uniformMatrix3fv(u_all_loc, false, genMat3ForGL(scaleDomX.value,
scaleDomY.value, rotateDom.value, offsetDomX.value, offsetDomY.value
))
gl.uniform1f(u_t, catDom.value)
gl.activeTexture(gl.TEXTURE0 + 0)
gl.bindTexture(gl.TEXTURE_2D, textureList[0 + 0])
gl.uniform1i(u_EyeLocation, 0 + 0)
gl.activeTexture(gl.TEXTURE0 + 1)
gl.bindTexture(gl.TEXTURE_2D, textureList[0 + 1])
gl.uniform1i(u_FunnyCatLocation, 0 + 1)
scaleValueDomX.innerText = scaleDomX.value
offsetValueDomX.innerText = offsetDomX.value
scaleValueDomY.innerText = scaleDomY.value
offsetValueDomY.innerText = offsetDomY.value
rotateValueDom.innerText = rotateDom.value
catValueDom.innerText = catDom.value
gl.enable(gl.CULL_FACE)
gl.enable(gl.DEPTH_TEST)
gl.clearColor(0, 0, 0, 0)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.drawArrays(gl.TRIANGLES, 0, pointCount)
}
function isPowerOf2(value) {
return (value & (value - 1)) === 0
}
var imageUrlList = ["images/eye.png", "images/funny-cat.jpg",]
var images_progress = 0
var textureList = []
function CreateTextureAndLoadImage() {
// 在 WebGL 里创建一个 texture
if (images_progress == imageUrlList.length) {
gl_draw()
return
}
let texture = gl.createTexture()
textureList.push(texture)
gl.bindTexture(gl.TEXTURE_2D, texture)
let image = new Image()
image.src = imageUrlList[images_progress]
console.log(image.src)
image.addEventListener('load', function () {
gl.activeTexture(gl.TEXTURE0 + images_progress)
gl.bindTexture(gl.TEXTURE_2D, textureList[images_progress])
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image)
if (isPowerOf2(image.width) && isPowerOf2(image.height)) {
gl.generateMipmap(gl.TEXTURE_2D)
} else {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
}
images_progress++
CreateTextureAndLoadImage()
})
}
Main()
models_tri.js
// 拿到一个平面方块的坐标点数组
function GetQuad(xcenter, ycenter, length) {
return [
// 左下角 // 右上角 // 左上角
-length / 2 + xcenter, -length / 2 + ycenter, 0,
length / 2 + xcenter, length / 2 + ycenter, 0,
-length / 2 + xcenter, length / 2 + ycenter, 0,
// 右下角
-length / 2 + xcenter, -length / 2 + ycenter, 0,
length / 2 + xcenter, -length / 2 + ycenter, 0,
length / 2 + xcenter, length / 2 + ycenter, 0,
]
}
function GetCube() {
return [
// front
-0.5, 0.5, -0.5,
-0.5, -0.5, -0.5,
0.5, 0.5, -0.5,
0.5, -0.5, -0.5,
0.5, 0.5, -0.5,
-0.5, -0.5, -0.5,
// back
-0.5, -0.5, 0.5,
0.5, 0.5, 0.5,
-0.5, 0.5, 0.5,
0.5, 0.5, 0.5,
-0.5, -0.5, 0.5,
0.5, -0.5, 0.5,
// left
-0.5, -0.5, 0.5,
-0.5, 0.5, -0.5,
-0.5, 0.5, 0.5,
-0.5, -0.5, 0.5,
-0.5, -0.5, -0.5,
-0.5, 0.5, 0.5,
]
}
function GetTri(A, B, C) {
return [A[0], A[1], B[0], B[1], C[0], C[1]]
}
function GetPolyN(center, R, N) {
// 1. 先在圆周上,均匀获取 N 个点
let idx = 0
let x = 0
let y = 0
let rad = 0
let pointArr = []
for (
rad = ((2 * Math.PI) / N) * idx
x = R * Math.cos(rad) + center[0]
y = R * Math.sin(rad) + center[1]
pointArr.push([x, y])
}
// 2. 将这N个点,每两个一组,与中心,正好是三个点,组成N个三角形
let res = []
for (idx = 0
res.push(...GetTri(pointArr[idx], pointArr[(idx + 1) % N], center))
}
return res
}
// 获取随机颜色 RGB
function GetRandomColor(pointCount) {
let res = []
let idx = 0
for (
res.push(Math.random())
res.push(Math.random())
res.push(Math.random())
// res.push(1)
// res.push(1)
// res.push(1)
}
return res
}