2011-09-13 18 views
19

Necesito recortar unos pocos cientos de objetos en un plano de recorte en OpenGL ES 2.0 y agradecería las ideas de las personas con más experiencia con este subconjunto de OpenGL.Trazado de recorte en OpenGL ES 2.0

En OpenGL ES 1.x hay glClipPlane. En el escritorio tiene glClipPlane, o gl_ClipDistance en su sombreador. Ninguno de estos dos está disponible en OpenGL ES 2.0. Parece que este tipo de funcionalidad desapareció por completo con 2.0.

Parece que la única forma de hacerlo es A) ejecute la ecuación del plano en el sombreador de fragmentos, o B) escriba un sombreador de vértices muy complejo que posicione los vértices en el plano si están detrás de él.

(A) sería lento en comparación con glClipPlane, ya que el recorte "regular" se realiza después del sombreador de vértices y antes del sombreador de fragmentos, cada fragmento tendría que ser parcialmente procesado y descartado.

(B) sería muy difícil hacer compatibles entre sombreadores, ya que no podemos descartar vértices tenemos que alinearlos con el plano y ajustar los atributos para los que están "cortados". No es posible interpolar entre vértices en el sombreado sin enviar todos los vértices en una textura y muestrearlo, lo que sería extremadamente costoso. A menudo, probablemente sería imposible interpolar los datos de forma correcta de todos modos.

También he pensado en alinear el avión cercano con el plano de recorte que sería una solución eficiente.

Y dibujar un plano después de representar toda la escena y comprobar la falla en profundidad tampoco funcionará (a menos que esté mirando cerca de la perpendicular al plano).

Lo que funciona para un solo objeto es dibujar el plano en el búfer de profundidad y luego renderizar el objeto con glDepthFunc (GL_GREATER), pero como se esperaba, no funciona cuando uno de los objetos está detrás de otro. Traté de construir sobre este concepto, pero finalmente terminé con algo muy similar a los volúmenes paralelos y tan caro.

Entonces, ¿qué es lo que me falta? ¿Cómo se haría el recorte plano en OpenGL ES 2.0?

Respuesta

5

Aparentemente estaba en algo cuando intenté cortar con la matriz de proyección. Exactamente cómo hacer esto se describe en este documento que encontré: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf

Espero que esto ayude a otras personas que buscan hacer esto.

+0

También se han encontrado con la falta de glClipPlane en GLES2. ¿Es este papel la mejor respuesta que tenemos? – Harold

+0

Las páginas 13-14 de este documento de ImageTec describen la misma técnica, pero en una presentación algo más simple. (http://www.imgtec.com/powervr/insider/docs/POWERVR.Shader%20Based%20Water%20Effects.1.11f.OGLES2External.pdf) –

1

No sé si esto se aplica a OpenGL ES, pero OpenGL tiene la salida variable gl_ClipDistance habilitada por glEnable (GL_CLIP_DISTANCE0). Una vez habilitada, la primitiva se recorta de forma que gl_ClipDistance [0]> = 0 después del vértice y sombreadores de geometría.

La distancia de las abrazaderas se pueden especificar como un simple producto de punto con una ecuación en el plano espacio-mundo:

http://github.prideout.net/clip-planes/

6

Aquí es dos soluciones que he encontrado en Vuforia SDK forums.

  1. Uso de shaders de Harri Smatt:

    uniform mat4 uModelM; 
    uniform mat4 uViewProjectionM; 
    attribute vec3 aPosition; 
    varying vec3 vPosition; 
    void main() { 
        vec4 pos = uModelM * vec4(aPosition, 1.0); 
        gl_Position = uViewProjectionM * pos; 
        vPosition = pos.xyz/pos.w; 
    } 
    

    precision mediump float; 
    varying vec3 vPosition; 
    void main() { 
        if (vPosition.z < 0.0) { 
        discard; 
        } else { 
        // Choose actual color for rendering.. 
        } 
    } 
    
  2. Uso quad en tampón de profundidad por Alessandro Boccalatte:

    • desactivar Color de escritura (es decir, conjunto el glColorMask(false, false, false, false);)
    • render un quad que coincide con la forma del marcador (es decir solo un quad con el mismo tamaño y posición/orientación del marcador); esto sólo se representará en el buffer de profundidad (porque desactivado la escritura la memoria de color en el paso anterior)
    • permitirá volver la máscara de color (glColorMask(true, true, true, true);)
    • hacen sus modelos 3D
0

Como la extensión EXT_clip_cull_distance no está disponible en OpenGL ES 2.0 (ya que para esta extensión se requiere OpenGL ES 3.0), se debe emular el recorte. Se puede emular en el sombreador de fragmentos, descartando fragmentos. Ver Fragment Shader - Special operations.

Véase también [Especificación de OpenGL ES Shading Language 1.00; 6.4 saltos; página 58]:

El descarte palabra clave sólo está permitido dentro shaders fragmento. Se puede usar dentro de un sombreador de fragmentos para abandonar la operación en el fragmento actual. Esta palabra clave hace que el fragmento se descarte y no se produzcan actualizaciones en los almacenamientos intermedios. Por lo general se utiliza dentro de una sentencia condicional, por ejemplo:

if (intensity < 0.0) 
    discard; 

Un programa de sombreado que emula gl_ClipDistance puede tener este aspecto:

Vertex Shader: shader

attribute vec3 inPos; 
attribute vec3 inCol; 

varying vec3 vertCol; 
varying float clip_distance; 

uniform mat4 u_projectionMat44; 
uniform mat4 u_viewMat44; 
uniform mat4 u_modelMat44; 
uniform vec4 u_clipPlane; 

void main() 
{ 
    vertCol  = inCol; 
    vec4 modelPos = u_modelMat44 * vec4(inPos, 1.0); 
    gl_Position = u_projectionMat44 * u_viewMat44 * viewPos; 
    clip_distance = dot(modelPos, u_clipPlane); 
} 

Fragmento:

varying vec3 vertPos; 
varying vec3 vertCol; 
varying float clip_distance; 

void main() 
{ 
    if (clip_distance < 0.0) 
     discard; 
    gl_FragColor = vec4(vertCol.rgb, 1.0); 
} 

El siguiente ejemplo de WebGL lo demuestra. Tenga en cuenta que el contexto WebGL 1.0 se ajusta estrechamente a la API OpenGL ES 2.0.

var readInput = true; 
 
    function changeEventHandler(event){ 
 
    readInput = true; 
 
    } 
 
    
 
    (function loadscene() { 
 
    
 
    var gl, progDraw, vp_size; 
 
    var bufCube = {}; 
 
    var clip = 0.0; 
 
    
 
    function render(delteMS){ 
 

 
     if (readInput) { 
 
      readInput = false; 
 
      clip = (document.getElementById("clip").value - 50)/50; 
 
     } 
 

 
     Camera.create(); 
 
     Camera.vp = vp_size; 
 
      
 
     gl.viewport(0, 0, vp_size[0], vp_size[1]); 
 
     gl.enable(gl.DEPTH_TEST); 
 
     gl.clearColor(0.0, 0.0, 0.0, 1.0); 
 
     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 
 

 
     // set up draw shader 
 
     ShaderProgram.Use(progDraw); 
 
     ShaderProgram.SetUniformM44(progDraw, "u_projectionMat44", Camera.Perspective()); 
 
     ShaderProgram.SetUniformM44(progDraw, "u_viewMat44", Camera.LookAt()); 
 
     var modelMat = IdentityMat44() 
 
     modelMat = RotateAxis(modelMat, CalcAng(delteMS, 13.0), 0); 
 
     modelMat = RotateAxis(modelMat, CalcAng(delteMS, 17.0), 1); 
 
     ShaderProgram.SetUniformM44(progDraw, "u_modelMat44", modelMat); 
 
     ShaderProgram.SetUniformF4(progDraw, "u_clipPlane", [1.0,-1.0,0.0,clip*1.7321]); 
 
     
 
     // draw scene 
 
     VertexBuffer.Draw(bufCube); 
 

 
     requestAnimationFrame(render); 
 
    } 
 
    
 
    function resize() { 
 
     //vp_size = [gl.drawingBufferWidth, gl.drawingBufferHeight]; 
 
     vp_size = [window.innerWidth, window.innerHeight] 
 
     canvas.width = vp_size[0]; 
 
     canvas.height = vp_size[1]; 
 
    } 
 
    
 
    function initScene() { 
 
    
 
     canvas = document.getElementById("canvas"); 
 
     gl = canvas.getContext("experimental-webgl"); 
 
     //gl = canvas.getContext("webgl2"); 
 
     if (!gl) 
 
     return null; 
 
     
 
     /* 
 
     var ext_frag_depth = gl.getExtension("EXT_clip_cull_distance"); // gl_ClipDistance gl_CullDistance 
 
     if (!ext_frag_depth) 
 
      alert('no gl_ClipDistance and gl_CullDistance support'); 
 
     */ 
 

 
     progDraw = ShaderProgram.Create( 
 
     [ { source : "draw-shader-vs", stage : gl.VERTEX_SHADER }, 
 
      { source : "draw-shader-fs", stage : gl.FRAGMENT_SHADER } 
 
     ]); 
 
     if (!progDraw.progObj) 
 
      return null; 
 
     progDraw.inPos = ShaderProgram.AttributeIndex(progDraw, "inPos"); 
 
     progDraw.inNV = ShaderProgram.AttributeIndex(progDraw, "inNV"); 
 
     progDraw.inCol = ShaderProgram.AttributeIndex(progDraw, "inCol"); 
 
     
 
     // create cube 
 
     var cubePos = [ 
 
     -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 
 
     -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0 ]; 
 
     var cubeCol = [ 1.0, 0.0, 0.0, 1.0, 0.5, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 ]; 
 
     var cubeHlpInx = [ 0, 1, 2, 3, 1, 5, 6, 2, 5, 4, 7, 6, 4, 0, 3, 7, 3, 2, 6, 7, 1, 0, 4, 5 ]; 
 
     var cubePosData = []; 
 
     for (var i = 0; i < cubeHlpInx.length; ++ i) { 
 
     cubePosData.push(cubePos[cubeHlpInx[i]*3], cubePos[cubeHlpInx[i]*3+1], cubePos[cubeHlpInx[i]*3+2]); 
 
     } 
 
     var cubeNVData = []; 
 
     for (var i1 = 0; i1 < cubeHlpInx.length; i1 += 4) { 
 
     var nv = [0, 0, 0]; 
 
     for (i2 = 0; i2 < 4; ++ i2) { 
 
      var i = i1 + i2; 
 
      nv[0] += cubePosData[i*3]; nv[1] += cubePosData[i*3+1]; nv[2] += cubePosData[i*3+2]; 
 
     } 
 
     for (i2 = 0; i2 < 4; ++ i2) 
 
     cubeNVData.push(nv[0], nv[1], nv[2]); 
 
     } 
 
     var cubeColData = []; 
 
     for (var is = 0; is < 6; ++ is) { 
 
     for (var ip = 0; ip < 4; ++ ip) { 
 
     cubeColData.push(cubeCol[is*3], cubeCol[is*3+1], cubeCol[is*3+2]); 
 
     } 
 
     } 
 
     var cubeInxData = []; 
 
     for (var i = 0; i < cubeHlpInx.length; i += 4) { 
 
     cubeInxData.push(i, i+1, i+2, i, i+2, i+3); 
 
     } 
 
     bufCube = VertexBuffer.Create(
 
     [ { data : cubePosData, attrSize : 3, attrLoc : progDraw.inPos }, 
 
     { data : cubeNVData, attrSize : 3, attrLoc : progDraw.inNV }, 
 
     { data : cubeColData, attrSize : 3, attrLoc : progDraw.inCol } ], 
 
     cubeInxData); 
 
     
 
     window.onresize = resize; 
 
     resize(); 
 
     requestAnimationFrame(render); 
 
    } 
 
    
 
    function Fract(val) { 
 
     return val - Math.trunc(val); 
 
    } 
 
    function CalcAng(deltaTime, intervall) { 
 
     return Fract(deltaTime/(1000*intervall)) * 2.0 * Math.PI; 
 
    } 
 
    function CalcMove(deltaTime, intervall, range) { 
 
     var pos = self.Fract(deltaTime/(1000*intervall)) * 2.0 
 
     var pos = pos < 1.0 ? pos : (2.0-pos) 
 
     return range[0] + (range[1] - range[0]) * pos; 
 
    }  
 
    function EllipticalPosition(a, b, angRag) { 
 
     var a_b = a * a - b * b 
 
     var ea = (a_b <= 0) ? 0 : Math.sqrt(a_b); 
 
     var eb = (a_b >= 0) ? 0 : Math.sqrt(-a_b); 
 
     return [ a * Math.sin(angRag) - ea, b * Math.cos(angRag) - eb, 0 ]; 
 
    } 
 
    
 
    glArrayType = typeof Float32Array !="undefined" ? Float32Array : (typeof WebGLFloatArray != "undefined" ? WebGLFloatArray : Array); 
 
    
 
    function IdentityMat44() { 
 
    var m = new glArrayType(16); 
 
    m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 0; 
 
    m[4] = 0; m[5] = 1; m[6] = 0; m[7] = 0; 
 
    m[8] = 0; m[9] = 0; m[10] = 1; m[11] = 0; 
 
    m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1; 
 
    return m; 
 
    }; 
 
    
 
    function RotateAxis(matA, angRad, axis) { 
 
     var aMap = [ [1, 2], [2, 0], [0, 1] ]; 
 
     var a0 = aMap[axis][0], a1 = aMap[axis][1]; 
 
     var sinAng = Math.sin(angRad), cosAng = Math.cos(angRad); 
 
     var matB = new glArrayType(16); 
 
     for (var i = 0; i < 16; ++ i) matB[i] = matA[i]; 
 
     for (var i = 0; i < 3; ++ i) { 
 
      matB[a0*4+i] = matA[a0*4+i] * cosAng + matA[a1*4+i] * sinAng; 
 
      matB[a1*4+i] = matA[a0*4+i] * -sinAng + matA[a1*4+i] * cosAng; 
 
     } 
 
     return matB; 
 
    } 
 
    
 
    function Cross(a, b) { return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0], 0.0 ]; } 
 
    function Dot(a, b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; } 
 
    function Normalize(v) { 
 
     var len = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); 
 
     return [ v[0]/len, v[1]/len, v[2]/len ]; 
 
    } 
 
    
 
    var Camera = {}; 
 
    Camera.create = function() { 
 
     this.pos = [0, 3, 0.0]; 
 
     this.target = [0, 0, 0]; 
 
     this.up  = [0, 0, 1]; 
 
     this.fov_y = 90; 
 
     this.vp  = [800, 600]; 
 
     this.near = 0.5; 
 
     this.far = 100.0; 
 
    } 
 
    Camera.Perspective = function() { 
 
     var fn = this.far + this.near; 
 
     var f_n = this.far - this.near; 
 
     var r = this.vp[0]/this.vp[1]; 
 
     var t = 1/Math.tan(Math.PI * this.fov_y/360); 
 
     var m = IdentityMat44(); 
 
     m[0] = t/r; m[1] = 0; m[2] = 0;        m[3] = 0; 
 
     m[4] = 0; m[5] = t; m[6] = 0;        m[7] = 0; 
 
     m[8] = 0; m[9] = 0; m[10] = -fn/f_n;      m[11] = -1; 
 
     m[12] = 0; m[13] = 0; m[14] = -2 * this.far * this.near/f_n; m[15] = 0; 
 
     return m; 
 
    } 
 
    Camera.LookAt = function() { 
 
     var mz = Normalize([ this.pos[0]-this.target[0], this.pos[1]-this.target[1], this.pos[2]-this.target[2] ]); 
 
     var mx = Normalize(Cross(this.up, mz)); 
 
     var my = Normalize(Cross(mz, mx)); 
 
     var tx = Dot(mx, this.pos); 
 
     var ty = Dot(my, this.pos); 
 
     var tz = Dot([-mz[0], -mz[1], -mz[2]], this.pos); 
 
     var m = IdentityMat44(); 
 
     m[0] = mx[0]; m[1] = my[0]; m[2] = mz[0]; m[3] = 0; 
 
     m[4] = mx[1]; m[5] = my[1]; m[6] = mz[1]; m[7] = 0; 
 
     m[8] = mx[2]; m[9] = my[2]; m[10] = mz[2]; m[11] = 0; 
 
     m[12] = tx; m[13] = ty; m[14] = tz; m[15] = 1; 
 
     return m; 
 
    } 
 
    
 
    var ShaderProgram = {}; 
 
    ShaderProgram.Create = function(shaderList) { 
 
     var shaderObjs = []; 
 
     for (var i_sh = 0; i_sh < shaderList.length; ++ i_sh) { 
 
      var shderObj = this.CompileShader(shaderList[i_sh].source, shaderList[i_sh].stage); 
 
      if (shderObj == 0) 
 
       return 0; 
 
      shaderObjs.push(shderObj); 
 
     } 
 
     var prog = {} 
 
     prog.progObj = this.LinkProgram(shaderObjs) 
 
     if (prog.progObj) { 
 
      prog.attribIndex = {}; 
 
      var noOfAttributes = gl.getProgramParameter(prog.progObj, gl.ACTIVE_ATTRIBUTES); 
 
      for (var i_n = 0; i_n < noOfAttributes; ++ i_n) { 
 
       var name = gl.getActiveAttrib(prog.progObj, i_n).name; 
 
       prog.attribIndex[name] = gl.getAttribLocation(prog.progObj, name); 
 
      } 
 
      prog.unifomLocation = {}; 
 
      var noOfUniforms = gl.getProgramParameter(prog.progObj, gl.ACTIVE_UNIFORMS); 
 
      for (var i_n = 0; i_n < noOfUniforms; ++ i_n) { 
 
       var name = gl.getActiveUniform(prog.progObj, i_n).name; 
 
       prog.unifomLocation[name] = gl.getUniformLocation(prog.progObj, name); 
 
      } 
 
     } 
 
     return prog; 
 
    } 
 
    ShaderProgram.AttributeIndex = function(prog, name) { return prog.attribIndex[name]; } 
 
    ShaderProgram.UniformLocation = function(prog, name) { return prog.unifomLocation[name]; } 
 
    ShaderProgram.Use = function(prog) { gl.useProgram(prog.progObj); } 
 
    ShaderProgram.SetUniformI1 = function(prog, name, val) { if(prog.unifomLocation[name]) gl.uniform1i(prog.unifomLocation[name], val); } 
 
    ShaderProgram.SetUniformF1 = function(prog, name, val) { if(prog.unifomLocation[name]) gl.uniform1f(prog.unifomLocation[name], val); } 
 
    ShaderProgram.SetUniformF2 = function(prog, name, arr) { if(prog.unifomLocation[name]) gl.uniform2fv(prog.unifomLocation[name], arr); } 
 
    ShaderProgram.SetUniformF3 = function(prog, name, arr) { if(prog.unifomLocation[name]) gl.uniform3fv(prog.unifomLocation[name], arr); } 
 
    ShaderProgram.SetUniformF4 = function(prog, name, arr) { if(prog.unifomLocation[name]) gl.uniform4fv(prog.unifomLocation[name], arr); } 
 
    ShaderProgram.SetUniformM33 = function(prog, name, mat) { if(prog.unifomLocation[name]) gl.uniformMatrix3fv(prog.unifomLocation[name], false, mat); } 
 
    ShaderProgram.SetUniformM44 = function(prog, name, mat) { if(prog.unifomLocation[name]) gl.uniformMatrix4fv(prog.unifomLocation[name], false, mat); } 
 
    ShaderProgram.CompileShader = function(source, shaderStage) { 
 
     var shaderScript = document.getElementById(source); 
 
     if (shaderScript) 
 
     source = shaderScript.text; 
 
     var shaderObj = gl.createShader(shaderStage); 
 
     gl.shaderSource(shaderObj, source); 
 
     gl.compileShader(shaderObj); 
 
     var status = gl.getShaderParameter(shaderObj, gl.COMPILE_STATUS); 
 
     if (!status) alert(gl.getShaderInfoLog(shaderObj)); 
 
     return status ? shaderObj : null; 
 
    } 
 
    ShaderProgram.LinkProgram = function(shaderObjs) { 
 
     var prog = gl.createProgram(); 
 
     for (var i_sh = 0; i_sh < shaderObjs.length; ++ i_sh) 
 
      gl.attachShader(prog, shaderObjs[i_sh]); 
 
     gl.linkProgram(prog); 
 
     status = gl.getProgramParameter(prog, gl.LINK_STATUS); 
 
     if (!status) alert("Could not initialise shaders"); 
 
     gl.useProgram(null); 
 
     return status ? prog : null; 
 
    } 
 
    
 
    var VertexBuffer = {}; 
 
    VertexBuffer.Create = function(attributes, indices) { 
 
     var buffer = {}; 
 
     buffer.buf = []; 
 
     buffer.attr = [] 
 
     for (var i = 0; i < attributes.length; ++ i) { 
 
      buffer.buf.push(gl.createBuffer()); 
 
      buffer.attr.push({ size : attributes[i].attrSize, loc : attributes[i].attrLoc }); 
 
      gl.bindBuffer(gl.ARRAY_BUFFER, buffer.buf[i]); 
 
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(attributes[i].data), gl.STATIC_DRAW); 
 
     } 
 
     buffer.inx = gl.createBuffer(); 
 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer.inx); 
 
     gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); 
 
     buffer.inxLen = indices.length; 
 
     gl.bindBuffer(gl.ARRAY_BUFFER, null); 
 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); 
 
     return buffer; 
 
    } 
 
    VertexBuffer.Draw = function(bufObj) { 
 
    for (var i = 0; i < bufObj.buf.length; ++ i) { 
 
      gl.bindBuffer(gl.ARRAY_BUFFER, bufObj.buf[i]); 
 
      gl.vertexAttribPointer(bufObj.attr[i].loc, bufObj.attr[i].size, gl.FLOAT, false, 0, 0); 
 
      gl.enableVertexAttribArray(bufObj.attr[i].loc); 
 
     } 
 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufObj.inx); 
 
     gl.drawElements(gl.TRIANGLES, bufObj.inxLen, gl.UNSIGNED_SHORT, 0); 
 
     for (var i = 0; i < bufObj.buf.length; ++ i) 
 
     gl.disableVertexAttribArray(bufObj.attr[i].loc); 
 
     gl.bindBuffer(gl.ARRAY_BUFFER, null); 
 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); 
 
    } 
 
    
 
    initScene(); 
 
    
 
    })();
html,body { 
 
    height: 100%; 
 
    width: 100%; 
 
    margin: 0; 
 
    overflow: hidden; 
 
} 
 

 
#gui { 
 
    position : absolute; 
 
    top : 0; 
 
    left : 0; 
 
}
<script id="draw-shader-vs" type="x-shader/x-vertex"> 
 
    precision highp float; 
 
    
 
    attribute vec3 inPos; 
 
    attribute vec3 inNV; 
 
    attribute vec3 inCol; 
 
    
 
    varying vec3 vertPos; 
 
    varying vec3 vertNV; 
 
    varying vec3 vertCol; 
 
    varying float clip_distance; 
 
    
 
    uniform mat4 u_projectionMat44; 
 
    uniform mat4 u_viewMat44; 
 
    uniform mat4 u_modelMat44; 
 
    uniform vec4 u_clipPlane; 
 
    
 
    void main() 
 
    { 
 
     mat4 mv  = u_viewMat44 * u_modelMat44; 
 
     vertCol  = inCol; 
 
     vertNV  = normalize(mat3(mv) * inNV); 
 
     vec4 viewPos = mv * vec4(inPos, 1.0); 
 
     vertPos  = viewPos.xyz; 
 
     gl_Position = u_projectionMat44 * viewPos; 
 

 
     vec4 modelPos = u_modelMat44 * vec4(inPos, 1.0); 
 
     vec4 clipPlane = vec4(normalize(u_clipPlane.xyz), u_clipPlane.w); 
 
     clip_distance = dot(modelPos, clipPlane); 
 
    } 
 
</script> 
 
    
 
<script id="draw-shader-fs" type="x-shader/x-fragment"> 
 
    precision mediump float; 
 

 
    varying vec3 vertPos; 
 
    varying vec3 vertNV; 
 
    varying vec3 vertCol; 
 
    varying float clip_distance; 
 
    
 
    void main() 
 
    { 
 
     if (clip_distance < 0.0) 
 
      discard; 
 
     vec3 color = vertCol; 
 
     gl_FragColor = vec4(color.rgb, 1.0); 
 
    } 
 
</script> 
 

 
<div> 
 
    <form id="gui" name="inputs"> 
 
     <table> 
 
      <tr> <td> <font color= #CCF>clipping</font> </td> 
 
       <td> <input type="range" id="clip" min="0" max="100" value="50" onchange="changeEventHandler(event);"/></td> </tr> 
 
     </table> 
 
    </form> 
 
</div> 
 

 

 
<canvas id="canvas" style="border: none;" width="100%" height="100%"></canvas>

Cuestiones relacionadas