2017-07-06 10 views
1

グラフを3次元で描画する必要があるアプリケーションで作業しています。 ノードは球で表され、私の最初の草稿では、glLinesをエッジとして描きます。太い線として描く円柱モデル

ここで線は太い線でなければならず、b)三次元のアプリケーションであるため、基本的に円筒形でなければなりません。

OpenGLで太い線を読んだ後、私はこれが比較的複雑であると考えました。特に3dの追加の円筒形が必要です。

私は「円筒モデルをとり、エッジを表現するためにそれを平行移動/回転/スケールするだけではない」と考えました。

それは私のためにうまく動作し、また私は行くつもりの外観を実現します。

「OpenGLの太い線」を調べるときに私がこれまでに似たようなことを見たことはありませんでしたが、私のアプローチで大きな欠点があるのか​​疑問でしたか?

+0

を始めています"OpenGLモード"で考えることができます。よくやった。 "太い線"を忘れてしまいます。 – Ripi2

+0

あなたが探しているものを見つけたい場合は、代わりに 'volumetric lines in opengl'を検索することをお勧めします – Jherico

答えて

0

私はあなたの曲線プロット

のレンダリングされた一部の多項式/コントロールポイントはそう、チャンクにあなたのプロットを分割フィット多項式やキュービック補間を使用GLSL

  1. パス補間を使用します。

  2. はあなたの曲線に断片の断片

    計算距離であなたの実際にレンダリングされたチャンク

  3. を覆う矩形を描画し、それをレンダリング(色距離に基づく)又はシリンダ半径、より遠い場合は、それを捨てるのいずれか。ここで

あなたの仕事のお手伝いをすることができますいくつかの関連QA S:

0

そこに多くの可能な解決策がありますが、あなたができることは以下の通りです:

  • は、色平面にバインドされたテクスチャ(espacially深度バッファ)

  • でフレームバッファにシリンダーをレンダリング
  • ポストスクリーンのスペースパスを描画し、テクスチャを入力として使用します。

  • テクスチャ全体の奥行きの違いを分析し、大きな違いがあった場所を描画します。

次のようになります深さを分析機能:

float DepthEdgeDist(in sampler2D colorSampler, in vec2 texCoord) 
{ 
    float dx = 2.0/u_textureSize.x; 
    float dy = 2.0/u_textureSize.y; 
    float s00 = Depth(colorSampler, texCoord.st + vec2(-dx, dy)); 
    float s10 = Depth(colorSampler, texCoord.st + vec2(-dx, 0.0)); 
    float s20 = Depth(colorSampler, texCoord.st + vec2(-dx, -dy)); 
    float s01 = Depth(colorSampler, texCoord.st + vec2(0.0, dy)); 
    float s21 = Depth(colorSampler, texCoord.st + vec2(0.0,- dy)); 
    float s02 = Depth(colorSampler, texCoord.st + vec2( dx, dy)); 
    float s12 = Depth(colorSampler, texCoord.st + vec2( dx, 0.0)); 
    float s22 = Depth(colorSampler, texCoord.st + vec2( dx, -dy)); 
    float sx = s00 + 2.0 * s10 + s20 - (s02 + 2.0 * s12 + s22); 
    float sy = s00 + 2.0 * s01 + s02 - (s20 + 2.0 * s21 + s22); 
    return sx * sx + sy * sy; 
} 

可能結果のための完全なWebGLの例を参照してください:あなたは

<script type="text/javascript"> 
 

 
draw_vert = 
 
"precision mediump float; \n" + 
 
"attribute vec3 inPos; \n" + 
 
"uniform mat4 u_projectionMat44;" + 
 
"uniform mat4 u_viewMat44;" + 
 
"uniform mat4 u_modelMat44;" + 
 
"void main()" + 
 
"{" + 
 
" vec4 modolPos = u_modelMat44 * vec4(inPos, 1.0);" + 
 
" vec4 viewPos = u_viewMat44 * modolPos;" + 
 
" gl_Position = u_projectionMat44 * viewPos;" + 
 
"}"; 
 

 
draw_frag = 
 
"precision mediump float; \n" + 
 
"void main()" + 
 
"{" + 
 
" float depth = abs(gl_FragCoord.z/gl_FragCoord.w);" + 
 
" gl_FragColor = vec4(vec3(depth), 1.0);" + 
 
"}"; 
 

 
post_vert = 
 
"precision mediump float; \n" + 
 
"attribute vec2 inPos; \n" + 
 
"varying vec2 pos;" + 
 
"void main()" + 
 
"{" + 
 
" pos = inPos;" + 
 
" gl_Position = vec4(inPos, 0.0, 1.0);" + 
 
"}"; 
 

 
post_frag = 
 
"precision mediump float; \n" + 
 
"varying vec2 pos;" + 
 
"uniform sampler2D u_texture;" + 
 
"uniform vec2 u_textureSize;" + 
 
"" + 
 
"float Depth(in sampler2D depthSampler, in vec2 texC)" + 
 
"{" + 
 
" float depth = texture2D(depthSampler, texC.st).x;" + 
 
" return depth;" + 
 
"}" + 
 
"" + 
 
"float DepthEdgeDist(in sampler2D colorSampler, in vec2 texCoord)" + 
 
"{" + 
 
" float dx = 2.0/u_textureSize.x;" + 
 
" float dy = 2.0/u_textureSize.y;" + 
 
" float s00 = Depth(colorSampler, texCoord.st + vec2(-dx, dy));" + 
 
" float s10 = Depth(colorSampler, texCoord.st + vec2(-dx, 0.0));" + 
 
" float s20 = Depth(colorSampler, texCoord.st + vec2(-dx, -dy));" + 
 
" float s01 = Depth(colorSampler, texCoord.st + vec2(0.0, dy));" + 
 
" float s21 = Depth(colorSampler, texCoord.st + vec2(0.0,- dy));" + 
 
" float s02 = Depth(colorSampler, texCoord.st + vec2( dx, dy));" + 
 
" float s12 = Depth(colorSampler, texCoord.st + vec2( dx, 0.0));" + 
 
" float s22 = Depth(colorSampler, texCoord.st + vec2( dx, -dy));" + 
 
" float sx = s00 + 2.0 * s10 + s20 - (s02 + 2.0 * s12 + s22);" + 
 
" float sy = s00 + 2.0 * s01 + s02 - (s20 + 2.0 * s21 + s22);" + 
 
" return sx * sx + sy * sy;" + 
 
" }" + 
 
"" + 
 
"void main()" + 
 
"{" + 
 
" vec2 texC = pos * 0.5 + 0.5;" + 
 
" float edgeDist = DepthEdgeDist(u_texture, texC.st);" + 
 
" gl_FragColor = vec4(vec3(1.0 - edgeDist), 1.0);" + 
 
"}"; 
 

 
glArrayType = typeof Float32Array !="undefined" ? Float32Array : (typeof WebGLFloatArray != "undefined" ? WebGLFloatArray : Array); 
 

 
function IdentityMat44() { 
 
    var a=new glArrayType(16); 
 
    a[0]=1;a[1]=0;a[2]=0;a[3]=0;a[4]=0;a[5]=1;a[6]=0;a[7]=0;a[8]=0;a[9]=0;a[10]=1;a[11]=0;a[12]=0;a[13]=0;a[14]=0;a[15]=1; 
 
    return a; 
 
}; 
 

 
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, 8, 0.5]; 
 
    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; 
 
} 
 
function ToVP(v) { return [ v[1], v[2], -v[0] ] } 
 
Camera.LookAt = function() { 
 
    var p = ToVP(this.pos); t = ToVP(this.target); u = ToVP(this.up); 
 
    var mx = Normalize([ t[0]-p[0], t[1]-p[1], t[2]-p[2] ]); 
 
    var my = Normalize(Cross(u, mx)); 
 
    var mz = Normalize(Cross(mx, my)); 
 
    var eyeInv = [ -this.pos[0], -this.pos[1], -this.pos[2] ]; 
 
    var tx = Dot(eyeInv, [mx[0], my[0], mz[0]]); 
 
    var ty = Dot(eyeInv, [mx[1], my[1], mz[1]]); 
 
    var tz = Dot(eyeInv, [mx[2], my[2], mz[2]]); 
 
    var m = IdentityMat44(); 
 
    m[0] = mx[0]; m[1] = mx[1]; m[2] = mx[2]; m[3] = 0; 
 
    m[4] = my[0]; m[5] = my[1]; m[6] = my[2]; m[7] = 0; 
 
    m[8] = mz[0]; m[9] = mz[1]; m[10] = mz[2]; m[11] = 0; 
 
    m[12] = tx; m[13] = ty; m[14] = tz; m[15] = 1; 
 
    return m; 
 
} 
 

 
// shader program object 
 
var ShaderProgram = {}; 
 
ShaderProgram.Create = function(shaderList, uniformNames) { 
 
    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 progObj = this.LinkProgram(shaderObjs) 
 
    if (progObj != 0) { 
 
     progObj.unifomLocation = {}; 
 
     for (var i_n = 0; i_n < uniformNames.length; ++ i_n) { 
 
      var name = uniformNames[i_n]; 
 
      progObj.unifomLocation[name] = gl.getUniformLocation(progObj, name); 
 
     } 
 
    } 
 
    return progObj; 
 
} 
 
ShaderProgram.Use = function(progObj) { gl.useProgram(progObj); } 
 
ShaderProgram.SetUniformInt = function(progObj, name, val) { gl.uniform1i(progObj.unifomLocation[name], val); } 
 
ShaderProgram.SetUniform2f = function(progObj, name, arr) { gl.uniform2fv(progObj.unifomLocation[name], arr); } 
 
ShaderProgram.SetUniformMat44 = function(progObj, name, mat) { gl.uniformMatrix4fv(progObj.unifomLocation[name], false, mat); } 
 
ShaderProgram.CompileShader = function(source, shaderStage) { 
 
    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 : 0; 
 
} 
 
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 : 0; 
 
} 
 
     
 

 
function drawScene(){ 
 

 
    var canvas = document.getElementById("camera-canvas"); 
 
    Camera.create(); 
 
    Camera.vp = [canvas.width, canvas.height]; 
 
    var currentTime = Date.now(); 
 
    var deltaMS = currentTime - startTime; 
 
    Camera.pos = EllipticalPosition(8, 5.5, CalcAng(currentTime, 10.0)); 
 
     
 
    gl.viewport(0, 0, canvas.width, canvas.height); 
 
    gl.enable(gl.DEPTH_TEST); 
 
    gl.clearColor(0.0, 0.0, 0.0, 1.0); 
 

 
    // set up framebuffer 
 
    gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 
 
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 
 
    
 
    // set up draw shader 
 
    ShaderProgram.Use(progDraw); 
 
    ShaderProgram.SetUniformMat44(progDraw, "u_projectionMat44", Camera.Perspective()); 
 
    ShaderProgram.SetUniformMat44(progDraw, "u_viewMat44", Camera.LookAt()); 
 
    ShaderProgram.SetUniformMat44(progDraw, "u_modelMat44", IdentityMat44()); 
 

 
    // draw scene 
 
    gl.enableVertexAttribArray(progDraw.inPos); 
 
    gl.bindBuffer(gl.ARRAY_BUFFER, bufObj.pos); 
 
    gl.vertexAttribPointer(progDraw.inPos, 3, gl.FLOAT, false, 0, 0); 
 
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufObj.inx); 
 
    gl.drawElements(gl.TRIANGLES, bufObj.inxLen, gl.UNSIGNED_SHORT, 0); 
 
    gl.disableVertexAttribArray(bufObj.pos); 
 

 
    // reset framebuffer and bind frambuffer texture 
 
    gl.bindFramebuffer(gl.FRAMEBUFFER, null); 
 
    gl.clearColor(1.0, 1.0, 1.0, 1.0); 
 
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 
 
    var texUnit = 0; 
 
    gl.activeTexture(gl.TEXTURE0 + texUnit); 
 
    gl.bindTexture(gl.TEXTURE_2D, fb.color0_texture); 
 

 
    // set up post process shader 
 
    ShaderProgram.Use(progPost); 
 
    ShaderProgram.SetUniformInt(progPost, "u_texture", texUnit) 
 
    ShaderProgram.SetUniform2f(progPost, "u_textureSize", [ fb.width, fb.height ]); 
 
    
 
    // draw full screen space 
 
    gl.enableVertexAttribArray(progPost.inPos); 
 
    gl.bindBuffer(gl.ARRAY_BUFFER, bufQuad.pos); 
 
    gl.vertexAttribPointer(progPost.inPos, 2, gl.FLOAT, false, 0, 0); 
 
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufQuad.inx); 
 
    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); 
 
    gl.disableVertexAttribArray(bufQuad.pos); 
 
} 
 

 
var startTime; 
 
function Fract(val) { 
 
    return val - Math.trunc(val); 
 
} 
 
function CalcAng(currentTime, intervall) { 
 
    return Fract((currentTime - startTime)/(1000*intervall)) * 2.0 * Math.PI; 
 
} 
 
function CalcMove(currentTime, intervall, range) { 
 
    var pos = self.Fract((currentTime - startTime)/(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 ]; 
 
} 
 

 
var gl; 
 
var progDraw; 
 
var progPost; 
 
var bufObj = {}; 
 
var bufQuad = {}; 
 
function cameraStart() { 
 

 
    var canvas = document.getElementById("camera-canvas"); 
 
    var vp = [canvas.width, canvas.height]; 
 
    gl = canvas.getContext("experimental-webgl"); 
 
    if (!gl) 
 
     return; 
 

 
    progDraw = ShaderProgram.Create( 
 
     [ { source : draw_vert, stage : gl.VERTEX_SHADER }, 
 
     { source : draw_frag, stage : gl.FRAGMENT_SHADER } 
 
     ], 
 
     [ "u_projectionMat44", "u_viewMat44", "u_modelMat44"]); 
 
    progDraw.inPos = gl.getAttribLocation(progDraw, "inPos"); 
 
    if (progDraw == 0) 
 
     return; 
 

 
    progPost = ShaderProgram.Create( 
 
     [ { source : post_vert, stage : gl.VERTEX_SHADER }, 
 
     { source : post_frag, stage : gl.FRAGMENT_SHADER } 
 
     ], 
 
     [ "u_texture", "u_textureSize" ]); 
 
    progPost.inPos = gl.getAttribLocation(progPost, "inPos"); 
 
    if (progPost == 0) 
 
     return; 
 

 
    fb = gl.createFramebuffer(); 
 
    fb.width = vp[0]; 
 
    fb.height = vp[1]; 
 
    gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 
 
    fb.color0_texture = gl.createTexture(); 
 
    gl.bindTexture(gl.TEXTURE_2D, fb.color0_texture); 
 
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 
 
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 
 
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, fb.width, fb.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 
 
    fb.renderbuffer = gl.createRenderbuffer(); 
 
    gl.bindRenderbuffer(gl.RENDERBUFFER, fb.renderbuffer); 
 
    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, fb.width, fb.height); 
 
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fb.color0_texture, 0); 
 
    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, fb.renderbuffer); 
 
    gl.bindTexture(gl.TEXTURE_2D, null); 
 
    gl.bindRenderbuffer(gl.RENDERBUFFER, null); 
 
    gl.bindFramebuffer(gl.FRAMEBUFFER, null); 
 

 
    var pos = []; 
 
    var circumferenceCount = 32; 
 
    for (var cTB = 0; cTB < 2; cTB ++) { 
 
     var z = cTB == 0 ? -1.0 : 1.0; 
 
     for (var cInx = 0; cInx <= circumferenceCount; ++ cInx) { 
 
      var angle = 2.0 * Math.PI * cInx/circumferenceCount; 
 
      pos.push(Math.cos(angle), Math.sin(angle), z); 
 
     } 
 
    } 
 
    var inx = []; 
 
    for (var iInx = 0; iInx < circumferenceCount; ++ iInx) { 
 
     iB = iInx; 
 
     iT = iInx + circumferenceCount + 1; 
 
     inx.push(iB, iT+1, iT, iB, iB+1, iT+1); 
 
    } 
 
    bufObj.pos = gl.createBuffer(); 
 
    gl.bindBuffer(gl.ARRAY_BUFFER, bufObj.pos); 
 
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pos), gl.STATIC_DRAW); 
 
    bufObj.inx = gl.createBuffer(); 
 
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufObj.inx); 
 
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(inx), gl.STATIC_DRAW); 
 
    bufObj.inxLen = inx.length; 
 

 
    bufQuad.pos = gl.createBuffer(); 
 
    gl.bindBuffer(gl.ARRAY_BUFFER, bufQuad.pos); 
 
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0 ]), gl.STATIC_DRAW); 
 
    bufQuad.inx = gl.createBuffer(); 
 
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufQuad.inx); 
 
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([ 0, 1, 2, 0, 2, 3 ]), gl.STATIC_DRAW); 
 

 
    startTime = Date.now(); 
 
    setInterval(drawScene, 50); 
 
} 
 

 
</script> 
 

 
<body onload="cameraStart();"> 
 
    <canvas id="camera-canvas" style="border: none;" width="512" height="256"></canvas> 
 
</body>