我试图使用three.js和光线行进GLSL来了解体积渲染。我从一个numpy数组中得到了一些数据。
正在渲染的数据立方体在一侧更加不透明,在另一侧逐渐变为透明 - 就像这样(忽略线框,这只是为了一点方向)
然而,当你从更透明的一端看到立方体时,透明度似乎是“阻止”#34;透明度较低的一端(希望有意义)。像这样:
我不知道这是否相关,但我也有一个问题,即当相机略微位于立方体内部时,它会停止正确渲染。它会切断离相机最近的位,如下所示:
这是一个相关的问题,还是只是方法的限制。
代码在这里 https://github.com/niallrobinson/test-volume-rendering/blob/master/viewer.htmlhttps://github.com/niallrobinson/test-volume-rendering/blob/master/viewer.js https://github.com/niallrobinson/test-volume-rendering/blob/master/viewer.html
,第二遍着色器看起来像这样:
<script id="vertexShaderFirstPass" type="x-shader/x-vertex">
varying vec3 worldSpaceCoords;
void main(){
//Set the world space coordinates of the back faces vertices as output.
worldSpaceCoords = position + vec3(0.5, 0.5, 0.5); //move it from [-0.5;0.5] to [0,1]
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script id="fragmentShaderFirstPass" type="x-shader/x-fragment">
varying vec3 worldSpaceCoords;
void main(){
//The fragment's world space coordinates as fragment output.
gl_FragColor = vec4( worldSpaceCoords.x , worldSpaceCoords.y, worldSpaceCoords.z, 1 );
}
</script>
<!-- second pass shaders -->
<script id="vertexShaderSecondPass" type="x-shader/x-vertex">
varying vec3 worldSpaceCoords;
varying vec4 projectedCoords;
void main()
{
worldSpaceCoords = (modelMatrix * vec4(position + vec3(0.5, 0.5, 0.5), 1.0 )).xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
projectedCoords = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script id="fragmentShaderSecondPass" type="x-shader/x-fragment">
varying vec3 worldSpaceCoords;
varying vec4 projectedCoords;
uniform sampler2D firstPassTexture, dataTexture; //i.e. tex and cubeTex
uniform float steps;
uniform float alphaCorrection;
const int MAX_STEPS = 512;
vec3 dataDims = vec3(4, 4, 4);
vec4 sampleAs3DTexture(sampler2D tex, vec3 pos) {
// pos is in UV coords i.e. 0->1. We also want to interrogate out texture in the range 0->1
// however, our 3D dimensions are conceptually 4,4,4
float nTiles = dataDims.z;
float tileWidth = 1.0 / nTiles;
float p = pos.y * tileWidth + pos.x / nTiles;
float q = pos.z;
lowp vec4 sample = texture2D(tex, vec2(p, q)); //I think this fn might convert from 255 range to 0->1 range
vec4 returnSample = vec4(0.7, 0., 0., sample.x * alphaCorrection); // alpha is 255 in png so overwrite
return returnSample;
}
// max 2d size is 4096 x 4096
void main( void ) {
//Transform the coordinates it from [-1;1] to [0;1]
vec2 firstPassTexCoord = vec2(((projectedCoords.x / projectedCoords.w) + 1.0 ) / 2.0,
((projectedCoords.y / projectedCoords.w) + 1.0 ) / 2.0 );
//The back position is the world space position stored in the texture.
vec3 backPos = texture2D(firstPassTexture, firstPassTexCoord).xyz;
//The front position is the world space position of the second render pass.
vec3 frontPos = worldSpaceCoords;
//The direction from the front position to back position.
vec3 dir = backPos - frontPos;
float rayLength = length(dir);
//Calculate how long to increment in each step.
float delta = 1.0 / steps;
//The increment in each direction for each step.
vec3 deltaDirection = normalize(dir) * delta;
float deltaDirectionLength = length(deltaDirection);
//Start the ray casting from the front position.
vec3 currentPosition = frontPos;
//The color accumulator.
vec4 accumulatedColor = vec4(0.0);
//The alpha value accumulated so far.
float accumulatedAlpha = 0.0;
//How long has the ray travelled so far.
float accumulatedLength = 0.0;
//vec4 dataSample;
vec4 dataSample;
float alphaSample;
//Perform the ray marching iterations
for(int i = 0; i < MAX_STEPS; i++){
//Get the voxel intensity value from the 3D texture.
dataSample = sampleAs3DTexture(dataTexture, currentPosition);
//Allow the alpha correction customization
alphaSample = dataSample.a;
//Perform the composition.
accumulatedColor += (1.0 - accumulatedAlpha) * dataSample * alphaSample;
//accumulatedColor += dataSample;
//Store the alpha accumulated so far.
accumulatedAlpha += alphaSample;
//Advance the ray.
currentPosition += deltaDirection;
accumulatedLength += deltaDirectionLength;
//If the length traversed is more than the ray length, or if the alpha accumulated reaches 1.0 then exit.
if(accumulatedLength >= rayLength || accumulatedAlpha >= 1.0 )
break;
}
gl_FragColor = accumulatedColor;
}
</script>
先谢谢大家
编辑:经过一些实验,似乎问题是只渲染了多维数据集的外部。如果我在立方体的中间放置一些数据,你就什么也看不见。
编辑:事实上,它在前端表面上的唯一渲染数据。如果我反转光线行进方向(即将其更改为朝向相机),则只能在背面上查看
答案 0 :(得分:2)
认为它的排序!从tex查找返回的数据是vec4。然后用于增加accumulatedColor
。我将accumulatedColor
更改为vec3并仅将其增加.xyz
,这似乎可以解决问题
感谢所有看过的人