Путаница в шейдере Libgdx, рендеринге и рисовании

#opengl #libgdx #shader #render #draw

#opengl #libgdx #шейдер #рендеринг #рисовать

Вопрос:

на моей сцене Libgdx Scene2D я пытаюсь заставить актера мигать белым цветом. С OpenGLES 2.0 я понял, что для достижения этой цели мне нужно использовать шейдер, и у меня возникла проблема с его реализацией.

Моя цель — покрасить актера в сплошной белый цвет с учетом специфического игрового события. Проблема заключается в том, что при этом конкретном событии все на сцене становится белым (все действующие лица и фон), а не только текстуры выбранных действующих лиц.

Мой мировой класс — это то, где создается сцена. Он отображается следующим образом:

 public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
update();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
  

На этапе я использую актеров, которые определены в классе MyActor. У этого класса есть свой собственный
метод рисования, в котором я пытаюсь раскрасить актера сплошным белым цветом с помощью шейдера. Вот метод рисования:

 public void draw(Batch batch, float alpha) {
    if (flashing) {
        batch.setShader(shader);            
    }

    batch.flush();

    Color color = getColor();
    batch.setColor(color.r, color.g, color.b, color.a * alpha);

    batch.draw(tr, getX(), getY(), side/2, side/2, side, side, getScaleX(), getScaleY(), 0);        
}
  

Очевидно, я делаю что-то не так с пакетом. Вместо того, чтобы окрашивать этого одного актера в белый цвет, он окрашивает все. Кроме того, он остается белым даже после логического мигания = false;

Вот как я настроил свой шейдер в классе actor MyActor:

 ShaderProgram shader;
String vertexShader =
        "attribute vec4 a_position; n"  
        "attribute vec4 a_color;n"  
        "attribute vec2 a_texCoord0; n"  
        "uniform mat4 u_projTrans; n"  
        "varying vec4 v_color; n"  
        "varying vec2 v_texCoords; n"  
        "void main() { n"  
        "v_color = a_color; n"  
        "v_texCoords = a_texCoord0; n"  
        "gl_Position = u_projTrans * a_position; n"  
        "};";

String fragmentShader = "#ifdef GL_ESn"  
        "precision mediump float;n"  
        "#endifn"   "varying vec4 v_color;n"  
        "varying vec2 v_texCoords;n"  
        "uniform sampler2D u_texture;n"  
        "uniform float grayscale;n"  
        "void main()n"  
        "{n"  
        "vec4 texColor = texture2D(u_texture, v_texCoords);n"  
        "float gray = dot(texColor.rgb, vec3(5, 5, 5));n"  
        "texColor.rgb = mix(vec3(gray), texColor.rgb, grayscale);n"  
        " gl_FragColor = v_color * texColor;n"  
        "}";
  

Затем инициируется с:

 shader = new ShaderProgram(vertexShader, fragmentShader);
  

Что я делаю не так?

Я должен признать, что, вероятно, я неправильно понимаю, как пакет MyActor, метод рисования и методы рендеринга работают вместе!

Спасибо за ваше время

Комментарии:

1. Вы Shader где-нибудь сбрасываете, чтобы SpriteBatch Shader снова использовать defaukt? На самом деле в вашем случае я бы не стал этого делать с помощью a Shader , эта задача не такая сложная. Просто сохраните значение по умолчанию Texture и сплошной белый Texture цвет и скажите Texture t = flashing ? white : defau< , и draw the Texture t .

2. Привет, @Springrbua, спасибо за ваш ответ. Нет, я не думаю, что я где-нибудь сбросил шейдер, как я могу это сделать? Я бы предпочел не использовать второй набор белых текстур, созданных вручную, в моей игре должны быть десятки разных текстур, каждая с уникальной формой, поэтому программный подход выглядит намного лучше, я думаю

3. Вы можете и должны использовать TextureAtlas в любом случае, но вам нужно решить. Я думаю, если вы скажете batch.setShader(null) , что он снова использует значение по умолчанию Shader , но я не уверен.

4. Javadok setShader говорит: «Вызовите этот метод с нулевым аргументом, чтобы использовать шейдер по умолчанию «.

5. блестяще, это работает, спасибо. ЕСЛИ вы хотите написать это как ответ, я могу одобрить его для вас 🙂 Я уже использую TextureAtlas, но если я вас не понял, я не хочу вручную создавать png-файлы из дюжины спрайтов с белым сплошным цветом. Спасибо за ваше время

Ответ №1:

Проблема здесь в том, что вы никогда не устанавливаете значение Shader по умолчанию Shader , поэтому вы Spritebatch всегда используете «сплошной белый» Shader . В качестве javadock setShader(ShaderProgram shader) для sai вы можете сбросить Shader , вызвав setShader(null) .
Другой возможностью было бы использовать другой Texture для сплошного белого и просто сказать:

 Texture t = flashing ? whiteTexture : defaultTexture;
  

и draw Texture t .
Просто предложение: не используйте batch.flush() , если это не является абсолютно необходимым, потому flush() что вызывает вызов draw для GPU, и это требует некоторой производительности.

Комментарии:

1. большое спасибо, не только ваш ответ правильный, но и у вас слишком много времени для обсуждения заранее. У вас также есть хорошие предложения. Хорошего дня

2. Большое спасибо! Ты тоже 🙂