2015-05-14 1 views
2

Мы много работаем, пытаясь рендерить 3D-облачные поля в WebGL. Подход, который мы сделали до сих пор, очерчен here - начальная позиция каждого луча - это текущее положение на передней поверхности куба объема, а конечная позиция вычисляется из предыдущего прохода, который кодирует значения xyx vales как обратную сторону текстуры.Объемный рендеринг из внутреннего тома

Как мы можем продлить это действие, когда камера находится внутри тома? Нужно ли создавать кубы меньшего объема на лету? Можем ли мы просто сменить шейдер, чтобы начать маршировать с камеры, а не на переднюю грань, и проецировать на заднюю часть куба?

Мы не уверены, с чего начать!

Заранее благодарен

ответ

0

Рендеринг только за один проход.

В этот проход вы делаете только обратные лица. Положение камеры должно быть переведено из мировых координат в систему координат, которая создается тремя осями с размерами выставляемого объема. Ваша цель - создать матрицу 4x4, где все векторы столбца представляют собой векторы vec4 (..., 0) и x, y, z этих векторов, определяются направлениями оси x, y, z с длиной окна объема. Если ящик параллелен оси х, этот вектор равен (1,0,0). Если он растянут до (2,0,0), то это его собственная ось X, и это будет вектор-столбец для столбца 0 в матрице. Сделайте это с осью y и z с их длиной. Последний вектор столбца в матрице - это положение поля как vec4 (tx, ty, tz, 1), так как эта матрица затем определяет систему координат, и вы используете ее для преобразования положения камеры в однородную (0,0,0) - (1,1,1) поле объема.

Создайте обратную матрицу томов и умножьте кулачок как vec4 (campos, 1) с правой стороны на invVolMatrix. Отправьте полученный vec3 как UNIFORM в шейдер.

Извлеките только обратные поверхности с (0,0,0) - (1,1,1) координатами на соответствующие углы volBox - как вы это делали. Теперь у вас есть в вашем шейдере

  1. равномерной Кампос
  2. задняя поверхность Voltex координаты
  3. вы знаете, что ваш volbox является единичным кубом в локальной системе координат с диагональю от (0,0,0) до (1 , 1,1)

В затенении сделать:

varying vec3 vLocalUnitTexCoord; // backface interpolated coordinate 
uniform vec3 LOCAL_CAM_POS;  // localised camPos 

struct AABB { 
    vec3 min; // (0,0,0) 
    vec3 max; // (1,1,1) 
}; 

struct Ray { 
    vec3 origin; vec3 dir; 
}; 

float getUnitAABBEntry(in Ray r) { 
    AABB b; 
    b.min = vec3(0); 
    b.max = vec3(1); 

    // compute clipping for box.min and box.max corner 
    vec3 rInvDir = vec3(1.0)/r.dir; 
    vec3 tMinima = (b.min - r.origin) * rInvDir; 
    vec3 tMaxima = (b.max - r.origin) * rInvDir; 

    // sort for nearest corner 
    vec3 tEntries = min(tMinima, tMaxima); 

    // find first real entry value of 3 t-distance values in vec3 container 
    vec2 tMaxEntryCandidates = max(vec2(tEntries.st), vec2(tEntries.pp)); 
    float tMaxEntry = max(tMaxEntryCandidates.s, tMaxEntryCandidates.t); 
} 

vec3 getCloserPos(in vec3 camera, in vec3 frontFaceIntersection, in float t) { 
    float useFrontCoord = 0.5 + 0.5 * sign(t); 
    vec3 startPos = mix(camera, frontFaceIntersection, useFrontCoord); 
    return startPos; 
} 

vec4 main(void) 
{ 
    Ray r; 
    r.origin = LOCAL_CAM_POS; 
    r.dir = normalize(vLocalUnitTexCoord - LOCAL_CAM_POS); 

    float t = getUnitAABBEntry(r); 
    vec3 frontFaceLocalUnitTexCoord = r.origin + r.dir * t; 
    vec3 startPos = getCloserPos(LOCAL_CAM_POS, frontFaceLocalUnitTexCoord, t); 

    // loop for integration follows here 
    vec3 start = startpos; 
    vec3 end = vLocalUnitTexCoord; 
    ...for loop..etc... 
} 

Счастливый кодирования!