2016-01-02 4 views
2

Итак, у меня довольно простая игра 2d в реальном времени, в которой я пытаюсь добавить приятное свечение. Чтобы довести его до самой основной формы, это просто круги и ложь, нарисованные на черной поверхности. И если вы считаете сцену с точки зрения цветового пространства hsv, все цвета (кроме черного) имеют значение «v» 100%.путаница затухания в реальном времени

В настоящее время у меня есть своего рода накопительный буфер, в котором текущий кадр соединен с предыдущим кадром. Он работает с использованием двух буферов вне экрана и черной текстуры.

  1. Буфер один активированного -------------
  2. линии и точки обращаются
  3. буфера один дезактивированного
  4. Буфера два активированных --------- ----
  5. Buffer два содержимых нарисованные как фул экран Quad
  6. Черного текстуры обращается с небольшой прозрачностью более полного экрана
  7. Buffer один содержанием обращается
  8. Buffer два деактивируется
  9. На буферах экрана активируется -------
  10. Buffer двоичного содержимого нарисованного на экран

Сейчас все «лаг», безусловно, происходит от задержки на процессоре. Графический процессор полностью справляется с этим.

Так что я думал о том, что, возможно, попытаюсь оживить вещи, добавив эффект свечения к вещам. Я думал, возможно, для шага 10 вместо использования обычного текстурного шейдера, я мог бы использовать тот, который рисует текстуру, за исключением свечения!

К сожалению, я немного смущен о том, как это сделать. Вот некоторые причины:

  • Blur stuff. В основном, что некоторые люди утверждают, что размытие Гаусса может быть сделано в режиме реального времени, в то время как другие говорят, что вы не должны. Также люди упоминают другой тип размытия, называемый «фокус», который я не знаю, что это такое.
  • Большинство примеров, которые я могу найти, используют XNA. Мне нужно иметь тот, который написан на языке шейдеров, который похож на OpenGL es 2.0.
  • Некоторые люди называют это свечением, другие называют это цветением
  • Различные режимы наложения? можно использовать для добавления свечения к исходной текстуре.
  • Как совместить вертикальное и горизонтальное размытие? Возможно, в одном призыве?

Во всяком случае, процесс, как я понимаю, для визуализации свечения, таким образом,

  1. Вырежьте темные данные из него
  2. Пятно света данных (с использованием гауссовой?)
  3. Blend, легкие данные по -top оригинала (смешение экрана?)

До сих пор я дошел до того, что у меня есть шейдер, который рисует текстуру. Как выглядит мой следующий шаг?

//Vertex 
percision highp float; 

attrivute vec2 positionCoords; 
attribute vec2 textureCoords; 
uniform mat4 matrix; 
uniform float alpha; 
varying vec2 v_texcoord; 
varying float o_alpha; 

void main() 
{ 
    gl_Position = matrix * vec4(positionCoords, 0.0, 1.0); 
    v_texcoord = textureCoords.xy; 
    o_alpha = alpha; 
} 



//Fragment 
varying vec2 v_texcoord; 
uniform sampler2D s_texture; 
varying float o_alpha; 

void main() 
{ 
    vec4 color = texture2D(s_texture, v_texcoord); 
    gl_FragColor = vec4(color.r, color.g, color.b, color.a - o_alpha); 
} 

Также это можно сделать в режиме реального времени?

Edit: Я, вероятно, хотите сделать 5px или меньшим размытием

ответ

0

Чтобы адресовать ваши первоначальные элементы путаницы:

  • Любой вид фильтра размывания будет эффективно распространяться каждый пиксель в сгусток на основе его оригинала положение и аккумулировать этот результат аддитивно для всех пикселей. Разница между фильтрами - это форма блоба.
    • Для размытия гауссова эта капля должна быть гладким градиентом, постепенно покрасневшим вокруг краев. Вероятно, вы хотите размытие Гаусса.
    • Размытие «фокус» было бы попыткой эмулировать камеру вне фокуса: она постепенно уменьшалась до нуля, а ее капли распространяли каждый пиксель по кругу с закругленными краями, что придавало бы тонко разный эффект.
  • Для простого однопроходного эффекта расчетная стоимость пропорциональна ширине размытия. Это означает, что узкое (например, 5px или меньше) размытие, вероятно, возможно в качестве одноразового эффекта в реальном времени. (В режиме реального времени можно добиться широкого размытия по Гауссу, используя несколько проходов и пирамиду с несколькими разрешениями, но я бы порекомендовал сначала попробовать что-то проще ...)
  • Вы можете разумно назвать эффект «светом» "или" цветут ". Однако для меня «свечение» означает узкое размытие, приводящее к неоновому эффекту, в то время как «цветение» означает использование широкого размытия для эмуляции визуального эффекта ярких объектов в визуальной среде с высоким динамическим диапазоном.
  • Режим наложения определяет, как то, что вы рисуете, сочетается с существующими цветами в целевом буфере. В OpenGL активируйте смешение с glEnable(GL_BLEND) и установите режим с помощью glBlendFunc().
  • Для узкого размытия вы должны иметь возможность выполнять горизонтальную и вертикальную фильтрацию за один проход.

Чтобы сделать быструю один проход выборки полноэкранного, вам нужно будет определить пиксель приращение в исходном текстуре. Это быстро, чтобы определить это статически, так что ваш фрагмент затенение не нужно вычислить его во время выполнения:

float dx = 1.0/x_resolution_drawn_over; 
float dy = 1.0/y_resolution_drawn_over; 

Вы можете сделать 3-пиксель (1,2,1) гауссово размытие в одном передать, установив режим выборки текстур в GL_LINEAR, и принимая 4 образца от источника текстуры t следующим образом:

float dx2 = 0.5*dx; float dy2 = 0.5*dy; // filter steps 

[...] 

vec2 a1 = vec2(x+dx2, y+dy2); 
vec2 a2 = vec2(x+dx2, y-dy2); 
vec2 b1 = vec2(x-dx2, y+dy2); 
vec2 b2 = vec2(x-dx2, y-dy2); 
result = 0.25*(texture(t,a1) + texture(t,a2) + texture(t,b1) + texture(t,b2)); 

Вы можете сделать 5-пиксельного (1,4,6,4,1) гауссово размывание в один перейдите, установив режим выборки текстуры на GL_LINEAR и взяв 9 образцов из исходной текстуры t следующим образом:

float dx12 = 1.2*dx; float dy12 = 1.2*dy; // filter steps 
float k0 = 0.375; float k1 = 0.3125; // filter constants 

vec4 filter(vec4 a, vec4 b, vec4 c) { 
    return k1*a + k0*b + k1*c; 
} 

[...] 

vec2 a1 = vec2(x+dx12, y+dy12); 
vec2 a2 = vec2(x,  y+dy12); 
vec2 a3 = vec2(x-dx12, y+dy12); 
vec4 a = filter(sample(t,a1), sample(t,a2), sample(t,a3)); 

vec2 b1 = vec2(x+dx12, y ); 
vec2 b2 = vec2(x,  y ); 
vec2 b3 = vec2(x-dx12, y ); 
vec4 b = filter(sample(t,b1), sample(t,b2), sample(t,b3)); 

vec2 c1 = vec2(x+dx12, y-dy12); 
vec2 c2 = vec2(x,  y-dy12); 
vec2 c3 = vec2(x-dx12, y-dy12); 
vec4 c = filter(sample(t,c1), sample(t,c2), sample(t,c3)); 

result = filter(a,b,c); 

Я не могу сказать, будут ли эти фильтры доступны в реальном времени на вашей платформе; 9 образцов/пикселей при полном разрешении могут быть медленными.

Любой более широкий гауссовый вариант сделает отдельные горизонтальные и вертикальные проходы более выгодными; существенно более широкий гауссовский режим потребует многоразовых технологий для работы в реальном времени.(Обратите внимание, что в отличие от гауссова фильтры, такие как размытие «фокус», не разделяются, что означает, что они не могут быть разделены на горизонтальные и вертикальные проходы ...)

0

Все, что сказал @comingstorm, верно, но есть намного проще. Не пишите размытие или свечение себя. Так как вы на iOS, почему бы не использовать CoreImage, у которого есть ряд интересных фильтров на выбор и которые работают в реальном времени? Например, у них есть фильтр Bloom, который, скорее всего, даст желаемые результаты. Также интересен фильтр Gloom.

Объединение фильтров CoreImage намного проще, чем создание шейдеров. Вы можете создать CIImage из текстуры OpenGL через [+CIImage imageWithTexture:size:flipped:colorSpace:].