2015-02-16 9 views
3

Я рисование спрайтов в буфер кадра для каждого пикселя для каждого шага в линии между двумя точками, но у меня есть проблема с смешиванием:libgdx - blendFunc для рисования линии кисти? (Добавка/неаддитивная смесь)

enter image description here

Я в настоящее время используется:

(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

Тогда в моем шейдера я:

if(color.a == 0) 
    color.rgb = 0; 

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


без присадок смешивания происходит этот эффект 3D:

enter image description here


Есть ли способ, чтобы иметь добавку смешивания цветов, как, но избежать, если цвета не соответствие?

Он должен выглядеть следующим образом:

enter image description here

+0

Я думал только вручную построения шейдера, который проходит кисть и framebuffer, но я не понимаю проекцию достаточно, чтобы получить правильные тексты для обеих текстур. – OneEyed

ответ

2

Вы можете сделать это, используя предварительно умноженную альфа.

Сначала вам необходимо правильно настроить текстуру. Нарисуйте его на черном, как это: enter image description here

Затем дублируйте яркость текстуры в ее альфа-канал. В GIMP вы можете сделать это, щелкнув правой кнопкой мыши по слою, выбрав «Добавить маску слоя», а затем «Копия слоя в оттенках серого». Это будет выглядеть вроде как это (как показано в Gimp):

enter image description here

Тогда вы можете перекрасить это канал RGB, если вам нравится, хотя это более универсален, чтобы оставить его белый и цвет его в вашем коде.

В своем коде, когда вы рисуете форму, используйте функцию смешивания для предварительного умноженного альфа:

batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA); 

И сделать это с помощью SpriteBatch по умолчанию шейдера в. После того, как вы нарисовали фигуру, переключиться обратно в обычную полупрозрачность: игра

batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); 

Примера:

enter image description here

public class GameMain extends ApplicationAdapter implements InputProcessor{ 
    SpriteBatch batch; 

    Texture star; 
    Color color = new Color(); 
    Viewport viewport; 
    int screenWidth, screenHeight; 
    FrameBuffer fbo; 
    boolean shouldClearFBO = false; 
    boolean fboUpdated = false; 
    OrthographicCamera fullScreenCamera; 

    boolean touchDown = false; 
    Vector2 touchLocation = new Vector2(); 

    int colorIndex = 0; 
    static final int[] COLORS = {0xff0000ff, 0x00ff00ff, 0x0000ffff, 0xffff00ff, 0xff00ffff, 0x00ffffff, 0xffffffff}; 

    static final float SIZE = 150; 

    @Override 
    public void create() { 
     batch = new SpriteBatch(); 
     star = new Texture("star.png"); 
     viewport = new ExtendViewport(800, 480); 
     fullScreenCamera = new OrthographicCamera(); 
     Gdx.input.setInputProcessor(this); 
    } 

    @Override 
    public void resize (int width, int height){ 
     viewport.update(width, height, true); 
     fullScreenCamera.setToOrtho(false, width, height); 
     fullScreenCamera.position.set(width/2, height/2, 0); 
     fullScreenCamera.update(); 
     fboUpdated = false; 
     screenWidth = width; 
     screenHeight = height; 
    } 

    @Override 
    public void render() { 
     if (!fboUpdated){ 
      fboUpdated = true; 
      if (fbo!=null) 
       fbo.dispose(); 
      fbo = new FrameBuffer(Pixmap.Format.RGBA8888, screenWidth, screenHeight, false); 
      fbo.begin(); 
      Gdx.gl.glClearColor(0, 0, 0, 1); 
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 
      fbo.end(); 
     } 

     color.set(COLORS[colorIndex]); 

     fbo.begin(); 
     if (shouldClearFBO){ 
      shouldClearFBO = false; 
      Gdx.gl.glClearColor(0, 0, 0, 1); 
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 
     } 
     if (touchDown){ 
      batch.setProjectionMatrix(viewport.getCamera().combined); 
      batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA); 
      batch.begin(); 
      batch.setColor(color); 
      batch.draw(star, touchLocation.x - SIZE/2, touchLocation.y - SIZE/2, SIZE, SIZE); 
      batch.end(); 
     } 
     fbo.end(); 

     Gdx.gl.glClearColor(0, 0, 0, 1); 
     Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); 
     batch.setColor(Color.WHITE); 
     batch.setProjectionMatrix(fullScreenCamera.combined); 
     batch.setBlendFunction(GL20.GL_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); 
     batch.begin(); 
     batch.draw(fbo.getColorBufferTexture(), 0, screenHeight, screenWidth, -screenHeight); 
     batch.end(); 
    } 

    @Override 
    public boolean keyDown(int keycode) { 
     switch (keycode){ 
      case Input.Keys.SPACE: 
       colorIndex = (++colorIndex) % COLORS.length; 
       return true; 
      case Input.Keys.X: 
       shouldClearFBO = true; 
       return true; 
     } 

     return false; 
    } 

    @Override 
    public boolean keyUp(int keycode) { 
     return false; 
    } 

    @Override 
    public boolean keyTyped(char character) { 
     return false; 
    } 

    @Override 
    public boolean touchDown(int screenX, int screenY, int pointer, int button) { 
     viewport.unproject(touchLocation.set(screenX, screenY)); 
     if (pointer==1){ 
       colorIndex = (++colorIndex) % COLORS.length; 
       return true; 
     } 
     if (pointer == 2){ 
      shouldClearFBO = true; 
      return true; 
     } 
     touchDown = true; 
     return true; 
    } 

    @Override 
    public boolean touchUp(int screenX, int screenY, int pointer, int button) { 
     touchDown = false; 
     return true; 
    } 

    @Override 
    public boolean touchDragged(int screenX, int screenY, int pointer) { 
     viewport.unproject(touchLocation.set(screenX, screenY)); 
     return true; 
    } 

    @Override 
    public boolean mouseMoved(int screenX, int screenY) { 
     return false; 
    } 

    @Override 
    public boolean scrolled(int amount) { 
     return false; 
    } 
} 
+0

Впечатляет! Когда я пытаюсь дублировать, я все еще получаю эффект 3D-кисти, используя: batch.setBlendFunction (GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA); Я считаю, что это может иметь какое-то отношение к атласу, который я использую, который создан с помощью TexturePacker, снабженного libgdx. Я скоро буду пытаться и обновлять. – OneEyed

+0

TexturePacker имеет опцию 'premultiplyAlpha'. Поэтому я думаю, что вы можете создать свои спрайты обычным способом (не преуспевайте в исходном изображении) и полагаться на TexturePacker для этого. Ваше исходное изображение может быть чисто белым в канале RGB и выглядеть как мое первое изображение выше в альфа-канале. Я этого не пробовал. – Tenfour04

+0

Он работает! Обработка изображения через GIMP, как вы наметили, отлично работает. Хотя, я не уверен, как дублировать этот метод в Photoshop. Я знаю свою проблему, хотя, моя текстура должна иметь значения RGB, соответствующие значению альфа. В настоящее время все они имеют (1,1,1) для цвета, а альфа - то, что меняется. – OneEyed

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

  • Нет связанных вопросов^_^