所以我已经开始在我的引擎中实现3d渲染,绘制一个立方体效果很好。所有面都正确渲染并且深度检查已打开。问题是我的渲染引擎有一个图层渲染系统,它们的顺序保存在一个循环的数组中。所以我将10个3d盒并排放在同一层上,相机不知道哪一个首先渲染。
每个3d框彼此分开渲染,移动相机不会更改任何渲染顺序。深度测试已启用。实现一个画家算法似乎对系统过于沉重,WebGL是否可以通过某种方式处理这个问题?
答案 0 :(得分:1)
深度测试是WebGL处理可见性的方式。我不确定你是如何在引擎中处理它的,但你可能在某个地方犯了错误。
我在下面提供了一个可能让您走上正轨的示例。
var sgl = function() {
"use strict";
var gl = null;
var programs = [];
var buffers = [];
var textures = [];
addEventListener("unload",function() {
for (var i = 0; i < programs.length; ++i) {
gl.deleteProgram(programs[i]);
}
for (var i = 0; i < buffers.length; ++i) {
gl.deleteBuffer(buffers[i]);
}
for (var i = 0; i < textures.length; ++i) {
gl.deleteTexture(textures[i]);
}
gl = null;
});
return {
set ctx(_gl) {
if (_gl instanceof WebGLRenderingContext) {
gl = _gl;
}
},
createProgram: function(vc,fc) {
if (!gl) {
return null;
}
var vs = gl.createShader(gl.VERTEX_SHADER);
var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vs,vc);
gl.shaderSource(fs,fc);
gl.compileShader(vs);
gl.compileShader(fs);
try {
if (!gl.getShaderParameter(vs,gl.COMPILE_STATUS)) {
throw "VS: " + gl.getShaderInfoLog(vs);
}
if (!gl.getShaderParameter(fs,gl.COMPILE_STATUS)) {
throw "FS: " + gl.getShaderInfoLog(fs);
}
} catch(log) {
gl.deleteShader(vs);
gl.deleteShader(fs);
console.error(log);
}
var p = gl.createProgram();
gl.attachShader(p,vs);
gl.attachShader(p,fs);
gl.linkProgram(p);
gl.deleteShader(vs);
gl.deleteShader(fs);
programs.push(p);
return p;
},
createIndexBuffer: function(d) {
d = d instanceof Uint16Array ? d : new Uint16Array(d);
var b = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,b);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,d,gl.STATIC_DRAW);
buffers.push(b);
return b;
},
createVertexBuffer: function(d) {
d = d instanceof Float32Array ? d : new Float32Array(d);
var b = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,b);
gl.bufferData(gl.ARRAY_BUFFER,d,gl.STATIC_DRAW);
buffers.push(b);
return b;
},
createTexture: function(pixels,width,height) {
var t = gl.createTexture();
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D,t);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.NEAREST);
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.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,width,height,0,gl.RGBA,gl.UNSIGNED_BYTE,pixels);
textures.push(t);
return t;
}
};
}();
void function() {
"use strict";
var canvasWidth = 180;
var canvasHeight = 160;
var canvas = null;
var gl = null;
var program = null;
var uLightDir = null;
var uModel = null;
var uView = null;
var uProj = null;
var uTexture = null;
var buffer = null;
var texture = null;
var modelMatrix = mat4.create();
var viewMatrix = mat4.create();
var projMatrix = mat4.perspective(
mat4.create(),
1.0472,
canvasWidth / canvasHeight,
1.0,
100.0
);
var instances = [];
var cameraAngle = 0.0;
var cameraDistance = 15.0;
var light = vec3.create();
var camera = vec3.fromValues(0,0,5);
var center = vec3.fromValues(0,0,0);
var up = vec3.fromValues(0,1,0);
onload = function() {
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
gl = canvas.getContext("webgl") || console.error("WebGL Not Supported.");
sgl.ctx = gl;
program = sgl.createProgram(`
precision lowp float;
const vec4 LIGHT_DIR = vec4(0.0,0.0,1.0,0.0);
attribute vec3 aPosition;
attribute vec3 aNormal;
attribute vec2 aUV;
varying float vDiffuse;
varying vec2 vUV;
uniform vec3 uLightDir;
uniform mat4 uModel;
uniform mat4 uView;
uniform mat4 uProj;
void main() {
vUV = aUV;
vDiffuse = max(0.4,dot(vec4(uLightDir,0.0),(uModel * vec4(aNormal,0.0))));
gl_Position = uProj * uView * uModel * vec4(aPosition,1.0);
}
`,`
precision lowp float;
varying float vDiffuse;
varying vec2 vUV;
uniform sampler2D uTexture;
void main() {
gl_FragColor = texture2D(uTexture,vUV) * vDiffuse;
}
`);
uLightDir = gl.getUniformLocation(program,"uLightDir");
uModel = gl.getUniformLocation(program,"uModel");
uView = gl.getUniformLocation(program,"uView");
uProj = gl.getUniformLocation(program,"uProj");
uTexture = gl.getUniformLocation(program,"uTexture");
buffer = sgl.createVertexBuffer([
// Position Normal UV
// Front
1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0,0.0,
-1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0,0.0,
-1.0,-1.0, 1.0, 0.0, 0.0, 1.0, 0.0,1.0,
-1.0,-1.0, 1.0, 0.0, 0.0, 1.0, 0.0,1.0,
1.0,-1.0, 1.0, 0.0, 0.0, 1.0, 1.0,1.0,
1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0,0.0,
// Back
-1.0,-1.0,-1.0, 0.0, 0.0,-1.0, 1.0,0.0,
-1.0, 1.0,-1.0, 0.0, 0.0,-1.0, 0.0,0.0,
1.0, 1.0,-1.0, 0.0, 0.0,-1.0, 0.0,1.0,
1.0, 1.0,-1.0, 0.0, 0.0,-1.0, 0.0,1.0,
1.0,-1.0,-1.0, 0.0, 0.0,-1.0, 1.0,1.0,
-1.0,-1.0,-1.0, 0.0, 0.0,-1.0, 1.0,0.0,
// Left
-1.0, 1.0, 1.0, -1.0, 0.0, 0.0, 0.0,0.0,
-1.0,-1.0,-1.0, -1.0, 0.0, 0.0, 1.0,1.0,
-1.0,-1.0, 1.0, -1.0, 0.0, 0.0, 0.0,1.0,
-1.0, 1.0, 1.0, -1.0, 0.0, 0.0, 0.0,0.0,
-1.0, 1.0,-1.0, -1.0, 0.0, 0.0, 1.0,0.0,
-1.0,-1.0,-1.0, -1.0, 0.0, 0.0, 1.0,1.0,
// Right
1.0,-1.0, 1.0, 1.0, 0.0, 0.0, 1.0,0.0,
1.0,-1.0,-1.0, 1.0, 0.0, 0.0, 0.0,0.0,
1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0,1.0,
1.0,-1.0,-1.0, 1.0, 0.0, 0.0, 0.0,0.0,
1.0, 1.0,-1.0, 1.0, 0.0, 0.0, 1.0,0.0,
1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0,1.0,
// Top
1.0, 1.0,-1.0, 0.0, 1.0, 0.0, 1.0,0.0,
-1.0, 1.0,-1.0, 0.0, 1.0, 0.0, 0.0,0.0,
1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0,1.0,
1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0,1.0,
-1.0, 1.0,-1.0, 0.0, 1.0, 0.0, 0.0,0.0,
-1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0,1.0,
// Bottom
1.0,-1.0, 1.0, 0.0,-1.0, 0.0, 1.0,1.0,
-1.0,-1.0,-1.0, 0.0,-1.0, 0.0, 0.0,0.0,
1.0,-1.0,-1.0, 0.0,-1.0, 0.0, 1.0,0.0,
-1.0,-1.0, 1.0, 0.0,-1.0, 0.0, 0.0,1.0,
-1.0,-1.0,-1.0, 0.0,-1.0, 0.0, 0.0,0.0,
1.0,-1.0, 1.0, 0.0,-1.0, 0.0, 1.0,1.0
]);
var width = 10;
var height = 10;
var pixels = new Uint8Array((width * height) << 2);
for (var i = 0; i < pixels.length; i += 4) {
var c = Math.random() < 0.5 ? 255 : 0;
pixels[i + 0] = c;
pixels[i + 1] = c;
pixels[i + 2] = c;
pixels[i + 3] = 255;
}
for (var x = 0; x < width; ++x) {
var index = x << 2;
pixels[index + 0] = 255;
pixels[index + 1] = 255;
pixels[index + 2] = 0;
pixels[index + 3] = 255;
index = (x + (height - 1) * width) << 2;
pixels[index + 0] = 255;
pixels[index + 1] = 255;
pixels[index + 2] = 0;
pixels[index + 3] = 255;
}
for (var y = 0; y < height; ++y) {
var index = (y * width) << 2;
pixels[index + 0] = 255;
pixels[index + 1] = 255;
pixels[index + 2] = 0;
pixels[index + 3] = 255;
index = ((width - 1) + y * width) << 2;
pixels[index + 0] = 255;
pixels[index + 1] = 255;
pixels[index + 2] = 0;
pixels[index + 3] = 255;
}
texture = sgl.createTexture(pixels,width,height);
gl.useProgram(program);
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
gl.vertexAttribPointer(0,3,gl.FLOAT,false,32,0);
gl.vertexAttribPointer(1,3,gl.FLOAT,false,32,12);
gl.vertexAttribPointer(2,2,gl.FLOAT,false,32,24);
gl.enableVertexAttribArray(0);
gl.enableVertexAttribArray(1);
gl.enableVertexAttribArray(2);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D,texture);
gl.enable(gl.CULL_FACE);
gl.enable(gl.DEPTH_TEST);
gl.clearColor(0.5,0.5,0.5,1.0);
gl.uniformMatrix4fv(uModel,false,modelMatrix);
gl.uniformMatrix4fv(uView,false,viewMatrix);
gl.uniformMatrix4fv(uProj,false,projMatrix);
var size = 5;
var hSize = size >> 1;
for (var x = -hSize << 1; x <= hSize << 1; x += 2) {
for (var y = -hSize << 1; y <= hSize << 1; y += 2) {
for (var z = -hSize << 1; z <= hSize << 1; z += 2) {
if (Math.random() < 0.3) {
instances.push(vec3.fromValues(x,y,z));
}
}
}
}
loop();
}
function loop() {
cameraAngle += 0.01;
if (cameraAngle > 2.0 * Math.PI) {
cameraAngle = 0.0;
}
camera[0] = Math.cos(cameraAngle) * cameraDistance;
camera[1] = 1.0;
camera[2] = Math.sin(cameraAngle) * cameraDistance;
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
vec3.sub(light,camera,center);
vec3.normalize(light,light);
gl.uniform3fv(uLightDir,light);
mat4.lookAt(viewMatrix,camera,center,up);
gl.uniformMatrix4fv(uView,false,viewMatrix);
for (var i = 0; i < instances.length; ++i) {
mat4.fromTranslation(modelMatrix,instances[i]);
gl.uniformMatrix4fv(uModel,false,modelMatrix);
gl.drawArrays(gl.TRIANGLES,0,36);
}
requestAnimationFrame(loop);
}
}();
&#13;
body {
background-color: black;
}
canvas {
display: block;
margin: 30px auto 0px auto;
border: solid 1px white;
border-radius: 10px;
}
script {
display: none;
}
&#13;
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script type="application/javascript" src="https://cdn.rawgit.com/toji/gl-matrix/8226d776/dist/gl-matrix-min.js"></script>
<canvas id="canvas"></canvas>
</body>
</html>
&#13;