简体   繁体   English

WebGL如何在3D中处理绘图顺序

[英]Webgl how to handle drawing order in 3d

So I have started to implement 3d rendering in my engine, drawing a single cube works great. 因此,我已经开始在引擎中实现3d渲染,绘制单个多维数据集效果很好。 All faces are correctly rendering and depth check is on. 所有面均已正确渲染,并且深度检查已启用。 The problem is that my rendering engine has a layer rendering system, their order is kept in an array that is looped through. 问题是我的渲染引擎有一个图层渲染系统,它们的顺序保存在一个循环的数组中。 So i place for example 10 3d boxes side by side on the same layer the camera wont know which one to render first. 因此,我将10个3d盒子并排放置在同一层上,而相机不会知道首先渲染哪个盒子。

在此处输入图片说明

Each 3d box is rendered separately from each other, and moving the camera doesnt change any rendering order. 每个3d框都是彼此分开渲染的,移动相机不会改变任何渲染顺序。 Depth test is enabled. 深度测试已启用。 Implementing a painters algorithm seems to be too taxing on the system, is there some way WebGL can handle this? 在系统上实施painters算法似乎太麻烦了,WebGL有什么方法可以解决这个问题?

Depth testing is how WebGL handles visibility. 深度测试是WebGL处理可见性的方式。 I'm not sure how you are handling it in your engine but you may have made a mistake somewhere. 我不确定您如何在引擎中处理它,但是您可能在某个地方犯了一个错误。

I've provided an example below that might put you on the right track. 我在下面提供了一个示例,可能使您走上正轨。

 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); } }(); 
 body { background-color: black; } canvas { display: block; margin: 30px auto 0px auto; border: solid 1px white; border-radius: 10px; } script { display: none; } 
 <!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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM