2016-04-05 86 views
0

我正在處理我的體繪製應用程序(C#+ OpenTK)。 使用光線投射渲染該卷時,我在此網站上發現了很多靈感: http://graphicsrunner.blogspot.sk/2009/01/volume-rendering-101.html,即使我的應用程序與OpenGL協同工作,使用3D紋理和其他內容的主要想法也是一樣的。 應用程序工作正常,但我「流入音量」(意味着在邊界框內)後,一切都消失了,我想要防止這種情況。那麼有沒有簡單的方法來做到這一點? - >我將能夠流過音量或移動音量。使用光線投射進行體積渲染 - 流過體積

這裏是片段着色器的代碼:

#version 330 

in vec3 EntryPoint; 
in vec4 ExitPointCoord; 

uniform sampler2D ExitPoints; 
uniform sampler3D VolumeTex; 
uniform sampler1D TransferFunc; 
uniform float  StepSize; 
uniform float  AlphaReduce; 
uniform vec2  ScreenSize; 
layout (location = 0) out vec4 FragColor; 

void main() 
{ 
//gl_FragCoord --> http://www.txutxi.com/?p=182 
vec3 exitPoint = texture(ExitPoints, gl_FragCoord.st/ScreenSize).xyz; 

//background need no raycasting 
if (EntryPoint == exitPoint) 
    discard; 

vec3 rayDirection = normalize(exitPoint - EntryPoint); 
vec4 currentPosition = vec4(EntryPoint, 0.0f); 
vec4 colorSum = vec4(.0f,.0f,.0f,.0f); 
vec4 color = vec4(0.0f,0.0f,0.0f,0.0f); 
vec4 value = vec4(0.0f); 

vec3 Step = rayDirection * StepSize; 
float stepLength= length(Step); 
float LengthSum = 0.0f; 
float Length = length(exitPoint - EntryPoint); 

for(int i=0; i < 16000; i++) 
{ 
    currentPosition.w = 0.0f; 
    value = texture(VolumeTex, currentPosition.xyz); 
    color = texture(TransferFunc, value.a); 

    //reduce the alpha to have a more transparent result 
    color.a *= AlphaReduce; 

    //Front to back blending 
    color.rgb *= color.a; 
    colorSum = (1.0f - colorSum.a) * color + colorSum; 

    //accumulate length 
    LengthSum += stepLength; 

    //break from the loop when alpha gets high enough 
    if(colorSum.a >= .95f) 
     break; 

    //advance the current position 
    currentPosition.xyz += Step; 

    //break if the ray is outside of the bounding box 
    if(LengthSum >= Length) 
     break; 
} 
FragColor = colorSum; 
} 

下面的代碼是基於https://github.com/toolchainX/Volume_Rendering_Using_GLSL

顯示()函數:

public void Display() 
    { 
     // the color of the vertex in the back face is also the location 
     // of the vertex 
     // save the back face to the user defined framebuffer bound 
     // with a 2D texture named `g_bfTexObj` 
     // draw the front face of the box 
     // in the rendering process, i.e. the ray marching process 
     // loading the volume `g_volTexObj` as well as the `g_bfTexObj` 
     // after vertex shader processing we got the color as well as the location of 
     // the vertex (in the object coordinates, before transformation). 
     // and the vertex assemblied into primitives before entering 
     // fragment shader processing stage. 
     // in fragment shader processing stage. we got `g_bfTexObj` 
     // (correspond to 'VolumeTex' in glsl)and `g_volTexObj`(correspond to 'ExitPoints') 
     // as well as the location of primitives. 

     // draw the back face of the box 
     GL.Enable(EnableCap.DepthTest); 

     //"vykreslim" front || back face objemu do framebuffru --> teda do 2D textury s ID bfTexID 
     //(pomocou backface.frag &.vert) 
     GL.BindFramebuffer(FramebufferTarget.Framebuffer, frameBufferID); 
     GL.Viewport(0, 0, width, height); 
     LinkShader(spMain.GetProgramHandle(), bfVertShader.GetShaderHandle(), bfFragShader.GetShaderHandle()); 
     spMain.UseProgram(); 
     //cull front face 
     Render(CullFaceMode.Front); 
     spMain.UseProgram(0); 
     //klasicky framebuffer --> "obrazovka" 
     GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); 

     GL.Viewport(0, 0, width, height); 
     LinkShader(spMain.GetProgramHandle(), rcVertShader.GetShaderHandle(), rcFragShader.GetShaderHandle()); 
     spMain.UseProgram(); 
     SetUniforms(); 
     Render(CullFaceMode.Back); 
     spMain.UseProgram(0); 

     GL.Disable(EnableCap.DepthTest); 
    } 

    private void DrawBox(CullFaceMode mode) 
    { 
     // --> Face culling allows non-visible triangles of closed surfaces to be culled before expensive Rasterization and Fragment Shader operations. 
     GL.Enable(EnableCap.CullFace); 
     GL.CullFace(mode); 
     GL.BindVertexArray(VAO); 
     GL.DrawElements(PrimitiveType.Triangles, 36, DrawElementsType.UnsignedInt, 0); 
     GL.BindVertexArray(0); 
     GL.Disable(EnableCap.CullFace); 
     spMain.UseProgram(0);//zapnuty bol v Render() ktora DrawBox zavolala 
    } 

    private void Render(CullFaceMode mode) 
    { 
     GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
     GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); 
     spMain.UseProgram(); 
     spMain.SetUniform("modelViewMatrix", Current); 
     spMain.SetUniform("projectionMatrix", projectionMatrix); 
     DrawBox(mode); 
    } 

的問題是(我想),該當我正在向音量方向移動時(我不移動相機,只是縮放音量),如果比例係數> 2.7,我就在音量中,這意味着「在飛機之後最終圖片被渲染「,所以一個什麼都看不到。 解決方案(也許),我能想到的,是類似的東西: 如果我達到比例係數= 2.7something:

1) - >不縮放量

2) - >以某種方式告訴片段着色器將EntryPoint朝着 RayDirection移動一段時間(可能基於比例因子)。現在

,我嘗試這個 「方法」,似乎它可以工作:(?或[0,1])

vec3 entryPoint = EntryPoint + some_value * rayDirection; 

的SOME_VALUE具有0,1 [間隔之間[待夾緊 ,但也許也沒關係感謝的到:

if (EntryPoint == exitPoint) 
discard; 

所以,現在,也許(如果我的解決方案不是那麼糟糕),我可以我的答案改成這樣: 如何計算SOME_VALUE(基於我發送給片段着色器的比例因子)?

if(scale_factor < 2.7something) 
    work like before; 
else 
{ 
    compute some_value; //(I need help with this part) 
    change entry point; 
    work like before; 
} 

(我不是以英語爲母語speeker,所以如果有文本進行一些大的錯誤,你不懂的東西,只是讓我知道,我會嘗試修復這些bug)

謝謝。

+0

爲了有效地幫助您,我們需要查看一些代碼。 –

回答

0

我解決了我的問題。它不會讓「被音量所包圍」的錯覺,但現在,我可以在音量中流動,沒有任何東西會消失。 這是添加到片段着色器我的解決方案的代碼:

vec3 entryPoint = vec3(0.0f); 

if(scaleCoeff >= 2.7f) 
{ 
    float tmp = min((scaleCoeff - 2.7f) * 0.1f, 1.0f); 
    entryPoint = EntryPoint + tmp * (exitPoint - EntryPoint); 
} 
else 
{ 
    entryPoint = EntryPoint; 
} 
// 

但如果你知道或可以想想更好的解決辦法,使「經卷被包圍」的效果,我如果你讓高興我知道。

謝謝。