#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? На самом деле в вашем случае я бы не стал этого делать с помощью aShader
, эта задача не такая сложная. Просто сохраните значение по умолчаниюTexture
и сплошной белыйTexture
цвет и скажитеTexture t = flashing ? white : defau<
, иdraw
theTexture 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. Большое спасибо! Ты тоже 🙂