2015-06-24 3 views
-1

Я пытаюсь разработать круговую диаграмму с использованием WebGL. Тем не менее, я получаю некоторые проблемы в разных версиях Chrome. В версии 40.0.2214.111 круговая диаграмма выглядит точно так, как я ожидал, с пятью различными частями.Круговая диаграмма WebGL - Различные результаты в разных версиях Chrome

Но когда я перехожу к версии 43.0.2357.130 цвета на моем втором и четвертом квадранте не совпадают, при этом черные и коричневые цвета меняются синим цветом. Вы можете получить пример here, чтобы проверить его.

Любые идеи, почему это происходит?

Vertex Shader

attribute vec2 aVertexPosition; 
    varying vec2 vTexCoord; 
    void main(){ 
     vTexCoord = aVertexPosition; 
     gl_Position = vec4(aVertexPosition, 0, 1); 
    } 

Фрагмент Shader

precision mediump float; 
    varying vec2 vTexCoord; 
    uniform int unumberOfParts; 
    void main(){ 

     vec4 angles = vec4(100.0, 110.0, 70.0, 30.0); 
     float prevAngle = radians(0.0); 
     float radQuad = radians(90.0); 
     float totalAngles = 0.0; 

     bool found = false; 
     bool hasRest = false; 
     float rad = 0.0; 
     float AngleToUse = 0.0; 
     float rest; 

     if (vTexCoord.y < 0.0 && vTexCoord.x < 0.0){ //Checks the coordinates of each quadrant 
      for (int i = 0; i<4;i++){ 
       totalAngles = totalAngles + angles[i]; 
       if (totalAngles > 90.0){ 
        rest = totalAngles - 90.0; 
        AngleToUse = angles[i] - rest; 
        hasRest = true; 
       } 
       else{ 
        AngleToUse = angles[i]; 
       } 
       rad = radians(AngleToUse); 
       if ((tan(rad + prevAngle) >= (vTexCoord.y)/(vTexCoord.x)) && (tan(prevAngle) <= (vTexCoord.y)/(vTexCoord.x))){ 
        float color = float(i) * 0.3; 
        if ((vTexCoord.x) * (vTexCoord.x) + (vTexCoord.y) * (vTexCoord.y) < 1.0){ 

            gl_FragColor = vec4(color, 0.0, 0.0, 1.0); 
            found = true; 

        } 
       } 
       prevAngle = prevAngle + rad; 
       if (totalAngles > 90.0){ 
        break; 
       } 
      } 

     } 

     if (vTexCoord.y < 0.0 && vTexCoord.x > 0.0){ 
      for (int i = 0; i<4;i++){ 
       totalAngles = totalAngles + angles[i]; 
       if (totalAngles >= 90.0){ 
        if (totalAngles - angles[i] < 90.0){ 
         AngleToUse = totalAngles - 90.0; 
        } 
        else if (totalAngles > 180.0){ 
         rest = totalAngles - 180.0; 
         AngleToUse = angles[i] - rest; 
         hasRest = true; 
        } 
        else{ 
         AngleToUse = angles[i]; 
        } 

        rad = radians(AngleToUse); 
        if ((tan(radQuad - (rad + prevAngle)) <= (vTexCoord.y)/-(vTexCoord.x)) && (tan(radQuad - (prevAngle)) >= (vTexCoord.y)/-(vTexCoord.x))){ 
         float color = float(i) * 0.3; 
         if ((vTexCoord.x) * (vTexCoord.x) + (vTexCoord.y) * (vTexCoord.y) < 1.0){ 
          //gl_FragColor = vec4(1, 0, 0, 1); 

             gl_FragColor = vec4(color, 0.0, 0.0, 1.0); 
             found = true; 

         } 
        } 
        prevAngle = prevAngle + rad; 
        if (totalAngles > 180.0){ 
         break; 
        } 

       } 
      } 
     } 

     else if (vTexCoord.y > 0.0 && vTexCoord.x > 0.0){ 
      for (int i = 0; i<4;i++){ 
       totalAngles = totalAngles + angles[i]; 
       if (totalAngles >= 180.0){ 
        if (totalAngles - angles[i] < 180.0){ 
         AngleToUse = totalAngles - 180.0; 
        } 
        else if (totalAngles > 270.0){ 
         rest = totalAngles - 270.0; 
         AngleToUse = angles[i] - rest; 
         hasRest = true; 
        } 
        else{ 
         AngleToUse = angles[i]; 
        } 

        rad = radians(AngleToUse); 
        if ((tan(rad + prevAngle) >= (vTexCoord.y)/(vTexCoord.x)) && (tan(prevAngle) <= (vTexCoord.y)/(vTexCoord.x))){ 
         float color = float(i) * 0.3; 
         if ((vTexCoord.x) * (vTexCoord.x) + (vTexCoord.y) * (vTexCoord.y) < 1.0){ 
          //gl_FragColor = vec4(1, 0, 0, 1); 

             gl_FragColor = vec4(color, 0.0, 0.0, 1.0); 
             found = true; 

         } 
        } 
        prevAngle = prevAngle + rad; 
        if (totalAngles > 270.0){ 
         break; 
        } 

       } 
      } 
      } 

      else if (vTexCoord.y > 0.0 && vTexCoord.x < 0.0){ 
      for (int i = 0; i<4;i++){ 
       totalAngles = totalAngles + angles[i]; 
       if (totalAngles >= 270.0){ 
        if (totalAngles - angles[i] < 270.0){ 
         AngleToUse = totalAngles - 270.0; 
        } 
        else{ 
         AngleToUse = angles[i]; 
        } 

        rad = radians(AngleToUse); 
        if ((tan((rad + prevAngle)) >= -(vTexCoord.x)/(vTexCoord.y)) && (tan((prevAngle)) <= -(vTexCoord.x)/(vTexCoord.y))){ 
         float color = float(i) * 0.3; 
         if ((vTexCoord.x) * (vTexCoord.x) + (vTexCoord.y) * (vTexCoord.y) < 1.0){ 
          //gl_FragColor = vec4(1, 0, 0, 1); 

             gl_FragColor = vec4(color, 0.0, 0.0, 1.0); 
             found = true; 

         } 
        } 
        prevAngle = prevAngle + rad; 
        if (totalAngles > 360.0){ 
         break; 
        } 

       } 
      } 
      } 



    if (found == false){ 
     if ((vTexCoord.x) * (vTexCoord.x) + (vTexCoord.y) * (vTexCoord.y) < 1.0){ 
      gl_FragColor = vec4(0, 0, 1, 1); 
     } 
     else{ 
      gl_FragColor = vec4(1, 1, 1, 0); 
     } 
    } 

    } 

WebGL

var c = document.getElementById('c'); 
var gl = c.getContext('experimental-webgl'); 

var vertexPosBuffer = gl.createBuffer(); 
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPosBuffer); 
var vertices = [-1, -1 , 1, -1, -1, 1 , 1, 1] 
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); 

vertexPosBuffer.itemSize = 2; 
vertexPosBuffer.numItems = 4; 
vertexPosBuffer.numberOfParts = 2; 

vs = document.getElementById('vshader').textContent; 
fs = document.getElementById('fshader').textContent; 

var program = createProgram(vs,fs); 
gl.useProgram(program); 
program.vertexPosAttrib = gl.getAttribLocation(program,'aVertexPosition'); 
program.numberOfParts = gl.getUniformLocation(program,'anumberOfParts'); 
gl.enableVertexAttribArray(program.vertexPosArray); 
gl.vertexAttribPointer(program.vertexPosAttrib, vertexPosBuffer.itemSize , gl.FLOAT, false , 0, 0); 
gl.uniform1i(program.numberOfParts, vertexPosBuffer.numberOfParts); 

gl.finish(); 
gl.drawArrays(gl.TRIANGLE_STRIP, 0 , vertexPosBuffer.numItems); 
+1

Это не столько ответ, сколько общий совет. Прежде всего, ваш шейдер настолько сумасшедший. С шейдером с таким количеством ветвей, это, вероятно, не намного эффективнее, чем это делается на процессоре. Во-вторых, с таким сложным шейдером будет очень сложно отлаживать. Попробуйте написать тот же алгоритм на стороне процессора и посмотреть, работает ли он правильно. В-третьих, для такого простого вывода вы могли бы достичь той же картины с лучшей производительностью, просто используя простой 2D-холст-рисунок (если только изучение OpenGL не является вашей целью в этом проекте). – aeskreis

+0

@aeskreis моя цель заключается в создании круговой диаграммы, которая будет размещена в месте расположения графика компоновки силы с до 10.000 узлов. Я попытался использовать D3 и другие библиотеки, но объем данных был большим, чтобы иметь динамический граф. Вот почему я использую WebGL. Я ничего не знаю о OpenGL, но я ничего не нашел о создании двумерных круговых диаграмм, поэтому я попытался создать свою. Любые идеи о том, как я могу упростить свой шейдер? –

+0

Одним из способов, который я мог бы придумать, чтобы оптимизировать это, было бы рисовать круговую диаграмму с каждым разделом, представленным в виде треугольника, с целью создания «квадратной» диаграммы. У вас будет координата положения, цвета и текстуры как ваши данные на вершину. Затем вы можете приложить альфа-маску, которая даст вам круговую форму, которую вы хотели. Это также даст вам некоторое базовое сглаживание (если ваша альфа-маска сглажена, это простая функция фотошопа или тому подобное).Я могу оставить ответ с более подробной информацией, если вы хотите. – aeskreis

ответ

0

Рассматривали вы с помощью некоторых вещь как спрайт для решения этой проблемы? Сначала создайте как 100 различных круговых диаграмм с разными уровнями полноты на двумерном холсте. Затем загрузите весь лист спрайтов на GPU. При рендеринге просто визуализируйте спрайт (часть спрайта) с желаемым уровнем наполнения.

Установка будет что-то вроде этого:

1) порождают все спрайты на 2D холст

2) загрузить холст GPU с texImage2D

3) для каждого спрайта, пред- вычислить значения uv на текстуре.

4) во время рендеринга определите правильные значения uv для использования, а затем просто визуализируйте стандартную текстуру с помощью шейдера vv.

5) наслаждайтесь!

Смежные вопросы