【发布时间】:2017-11-30 20:52:00
【问题描述】:
我创建了一个由地板(平面)、桌子和立方体组成的基本场景。我现在想使用木质纹理图像 Click to see the wooden texture. 对地板进行纹理处理,我对纹理知之甚少,而且对 WebGL 还很陌生。
我知道必须从我的目录中加载图像,但不确定如何将其应用到地板上。除此之外,我不确定平面(地板)所需的纹理顶点坐标。
我也知道我需要添加新属性以允许纹理化。您是否需要更改对象的整体布局才能产生纹理?
对于从哪里开始以及如何完成这项任务的任何建议,我们将不胜感激。
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>Drawing In 3D </title>
<meta charset="utf-8">
<script src="glMatrix.js"></script>
<script src="webgl-debug.js"></script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying vec4 vColor;
void main() {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vColor = aVertexColor;
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec4 vColor;
void main() {
gl_FragColor = vColor;
}
</script>
<script type="text/javascript">
var gl;
var canvas;
var shaderProgram;
var floorVertexPositionBuffer;
var floorVertexIndexBuffer;
var cubeVertexPositionBuffer;
var cubeVertexIndexBuffer;
var modelViewMatrix;
var projectionMatrix;
var modelViewMatrixStack;
function createGLContext(canvas) {
var names = ["webgl", "experimental-webgl"];
var context = null;
for (var i = 0; i < names.length; i++) {
try {
context = canvas.getContext(names[i]);
} catch (e) { }
if (context) {
break;
}
}
if (context) {
context.viewportWidth = canvas.width;
context.viewportHeight = canvas.height;
} else {
alert("Failed to create WebGL context!");
}
return context;
}
function loadShaderFromDOM(id) {
var shaderScript = document.getElementById(id);
if (!shaderScript) {
return null;
}
var shaderSource = "";
var currentChild = shaderScript.firstChild;
while (currentChild) {
if (currentChild.nodeType == 3) { // 3 corresponds to TEXT_NODE
shaderSource += currentChild.textContent;
}
currentChild = currentChild.nextSibling;
}
var shader;
if (shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader, shaderSource);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
function setupShaders() {
var vertexShader = loadShaderFromDOM("shader-vs");
var fragmentShader = loadShaderFromDOM("shader-fs");
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Failed to setup shaders");
}
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
shaderProgram.uniformMVMatrix = gl.getUniformLocation(shaderProgram, "uMVMatrix");
shaderProgram.uniformProjMatrix = gl.getUniformLocation(shaderProgram, "uPMatrix");
// Initialise the matrices
modelViewMatrix = mat4.create();
projectionMatrix = mat4.create();
modelViewMatrixStack = [];
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
}
function pushModelViewMatrix() {
var copyToPush = mat4.create(modelViewMatrix);
modelViewMatrixStack.push(copyToPush);
}
function popModelViewMatrix() {
if (modelViewMatrixStack.length == 0) {
throw "Error popModelViewMatrix() - Stack was empty ";
}
modelViewMatrix = modelViewMatrixStack.pop();
}
function setupFloorBuffers() {
floorVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, floorVertexPositionBuffer);
var floorVertexPosition = [
// Plane in y=0
5.0, 0.0, 5.0, //v0
5.0, 0.0, -5.0, //v1
-5.0, 0.0, -5.0, //v2
-5.0, 0.0, 5.0]; //v3
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(floorVertexPosition), gl.STATIC_DRAW);
floorVertexPositionBuffer.itemSize = 3;
floorVertexPositionBuffer.numberOfItems = 4;
floorVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, floorVertexIndexBuffer);
var floorVertexIndices = [0, 1, 2, 3];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(floorVertexIndices), gl.STATIC_DRAW);
floorVertexIndexBuffer.itemSize = 1;
floorVertexIndexBuffer.numberOfItems = 4;
}
function setupCubeBuffers() {
cubeVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
var cubeVertexPosition = [
1.0, 1.0, 1.0, //v0
-1.0, 1.0, 1.0, //v1
-1.0, -1.0, 1.0, //v2
1.0, -1.0, 1.0, //v3
1.0, 1.0, -1.0, //v4
-1.0, 1.0, -1.0, //v5
-1.0, -1.0, -1.0, //v6
1.0, -1.0, -1.0, //v7
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cubeVertexPosition), gl.STATIC_DRAW);
cubeVertexPositionBuffer.itemSize = 3;
cubeVertexPositionBuffer.numberOfItems = 8;
cubeVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
var cubeVertexIndices = [
0, 1, 2, 0, 2, 3, // Front face
4, 6, 5, 4, 7, 6, // Back face
1, 5, 6, 1, 6, 2, //left
0, 3, 7, 0, 7, 4, //right
0, 5, 1, 0, 4, 5, //top
3, 2, 6, 3, 6, 7 //bottom
];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
cubeVertexIndexBuffer.itemSize = 1;
cubeVertexIndexBuffer.numberOfItems = 36;
}
function setupBuffers() {
setupFloorBuffers();
setupCubeBuffers();
}
function uploadModelViewMatrixToShader() {
gl.uniformMatrix4fv(shaderProgram.uniformMVMatrix, false, modelViewMatrix);
}
function uploadProjectionMatrixToShader() {
gl.uniformMatrix4fv(shaderProgram.uniformProjMatrix, false, projectionMatrix);
}
function drawFloor(r, g, b, a) {
// Disable vertex attrib array and use constant color for the floor.
gl.disableVertexAttribArray(shaderProgram.vertexColorAttribute);
// Set colour
gl.vertexAttrib4f(shaderProgram.vertexColorAttribute, r, g, b, a);
// Draw the floor
gl.bindBuffer(gl.ARRAY_BUFFER, floorVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, floorVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, floorVertexIndexBuffer);
gl.drawElements(gl.TRIANGLE_FAN, floorVertexIndexBuffer.numberOfItems, gl.UNSIGNED_SHORT, 0);
}
function drawCube(r, g, b, a) {
// Disable vertex attrib array and use constant color for the cube.
gl.disableVertexAttribArray(shaderProgram.vertexColorAttribute);
// Set color
gl.vertexAttrib4f(shaderProgram.vertexColorAttribute, r, g, b, a);
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, cubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numberOfItems, gl.UNSIGNED_SHORT, 0);
}
function drawTable() {
// Draw table top
pushModelViewMatrix();
mat4.translate(modelViewMatrix, [0.0, 1.0, 0.0], modelViewMatrix);
mat4.scale(modelViewMatrix, [2.0, 0.1, 2.0], modelViewMatrix);
uploadModelViewMatrixToShader();
// Draw the scaled cube
drawCube(0.72, 0.53, 0.04, 1.0); // brown color
popModelViewMatrix();
// Draw table legs
for (var i = -1; i <= 1; i += 2) {
for (var j = -1; j <= 1; j += 2) {
pushModelViewMatrix();
mat4.translate(modelViewMatrix, [i * 1.9, -0.1, j * 1.9], modelViewMatrix);
mat4.scale(modelViewMatrix, [0.1, 1.0, 0.1], modelViewMatrix);
uploadModelViewMatrixToShader();
drawCube(0.72, 0.53, 0.04, 1.0); // argument sets brown color
popModelViewMatrix();
}
}
}
function draw() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(60, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, projectionMatrix);
mat4.identity(modelViewMatrix);
mat4.lookAt([8, 5, -10], [0, 0, 0], [0, 1, 0], modelViewMatrix);
uploadModelViewMatrixToShader();
uploadProjectionMatrixToShader();
// Draw floor in red color
drawFloor(1.0, 0.0, 0.0, 1.0);
// Draw table
pushModelViewMatrix();
mat4.translate(modelViewMatrix, [0.0, 1.1, 0.0], modelViewMatrix);
uploadModelViewMatrixToShader();
drawTable(); //Call drawTable() function
popModelViewMatrix();
// Draw box on top of the table
pushModelViewMatrix();
mat4.translate(modelViewMatrix, [0.0, 2.7, 0.0], modelViewMatrix);
mat4.scale(modelViewMatrix, [0.5, 0.5, 0.5], modelViewMatrix);
uploadModelViewMatrixToShader();
drawCube(0.0, 0.0, 1.0, 1.0);
popModelViewMatrix()
}
function startup() {
canvas = document.getElementById("myGLCanvas");
gl = WebGLDebugUtils.makeDebugContext(createGLContext(canvas));
setupShaders();
setupBuffers();
gl.clearColor(1.0, 1.0, 1.0, 1.0);
gl.enable(gl.DEPTH_TEST);
draw();
}
</script>
</head>
<body onload="startup();">
<canvas id="myGLCanvas" width="500" height="500"></canvas>
</body>
</html>
【问题讨论】:
-
你问的是一个相当大的话题。首先你需要知道如何使用texture coordinates and how to load images。要使用来自不同网站的图像,您需要了解 CORS permissions。您还需要知道run a simple web server 可能需要什么,否则 WebGL 将无法加载图像。
标签: javascript webgl