ПрограммированиеФорумГрафика

Libgdx shaders

#0
23:23, 12 янв 2015

Добрый вечер. Изучаю туториалы по шейдерам в Libgdx. Использую этот туториал. Пытаюсь нарисовать круг, получаю просто черную текстуру. Код шейдера ниже.
Шейдер

#ifdef GL_ES
  #define LOWP lowp
  precision mediump float;
#else
  #define LOWP
#endif

uniform sampler2D u_texture; 

uniform vec2 u_resolution;

varying LOWP vec4 v_color;
varying vec2 v_texCoord0;

const float RADIUS = 0.75;
const float SOFTNESS = 0.45;
const vec3 SEPIA = vec3(1.2, 1.0, 0.8);

void main() {
  vec4 texColor = texture2D(u_texture, v_texCoord0); 
  vec2 position = (gl_FragCoord.xy / u_resolution.xy) - vec2(0.5);
  float len = length(position);
  //gl_FragColor = texColor * v_color;
  
  float r = 0.5;
  float softness = 0.05;

  gl_FragColor = vec4( vec3( smoothstep(r, r-softness, len) ), 1.0 );
}

Класс

public class ShaderTest extends ApplicationAdapter {

  private SpriteBatch batch;
  private Texture img;
  private ShaderProgram shaderProgram;
  private OrthographicCamera cam;

  @Override
  public void create() {
    batch = new SpriteBatch();
    
    img = new Texture("scene.png");
    
    ShaderProgram.pedantic = false;
    shaderProgram = new ShaderProgram(Gdx.files.internal("shaders/lesson2.vp"), Gdx.files.internal("shaders/lesson3.fp"));
    if (!shaderProgram.isCompiled()) {
      System.out.println(shaderProgram.getLog());
    }
    
    batch.setShader(shaderProgram);
    
    cam = new OrthographicCamera(img.getWidth(), img.getHeight());
    cam.position.set(img.getWidth() / 2, img.getHeight() / 2, 0);
  }

  @Override
  public void resize(int width, int height) {
    System.out.println("resize");
    cam.setToOrtho(false, width, height);
    batch.setProjectionMatrix(cam.combined);
    shaderProgram.begin();
    shaderProgram.setUniformf("resolution", width, height);
    shaderProgram.end(); 
  }

  @Override
  public void render() {
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    
    //batch.setProjectionMatrix(cam.combined);
    batch.begin();
    batch.draw(img, 0, 0);
    batch.end();
  }

  @Override
  public void pause() {}

  @Override
  public void resume() {}

  @Override
  public void dispose() {
    shaderProgram.dispose();
    img.dispose();
    batch.dispose();
  }
}
#1
20:03, 13 янв 2015

Я ни яву ни либгдх не знаю,
но чет я не пойму, как оно должно рисовать что-то, если ты в шейдер ничего не передаешь,
кроме как u_resolution, который передается только при изменении размеров окна?
Тебе же надо передать туда текстуру и разрешение окна.
Итого в create методе запили :

    shaderProgram.begin();
    shaderProgram.setUniformf("resolution", width, height);
    shaderProgram.end();

А в методе render:

    img.bind(0); //<а текстурку то забиндить надо
    batch.begin();
    batch.draw(img, 0, 0);
    batch.end();

Это я бегло пробежался по твоей статье, может что-то упустил.

#2
21:44, 13 янв 2015

dmitryhryppa, там как бы все под LibGdx переделано, метод resize с передачей разрешения экрана запускается сразу после метода create и текстуры движок сам биндит.

#3
22:29, 13 янв 2015

Да? Ну это хорошо. Тогда просто поищи какая часть кода не работает...
Ну например в шейдере напиши:
gl_FragColor = texture2D(u_texture, v_texCoord0);
а остальные расчеты закоменти и посмотри выведется ли картинка.

#4
4:01, 14 янв 2015

Попробуй такой шейдер для отрисовки окружности диаметром, совпадающей с высотой экрана, и шириной "переходящей" части в 0.05

const float RADIUS = 0.5;
void main() {
vec4 texColor = texture2D(u_texture, vTexCoord);
vec2 position;
position.x = ((gl_FragCoord.x / resolution.x) - 0.5) * resolution.x/resolution.y; // иначе овал рисуется для неквадратного окна
position.y = ((gl_FragCoord.y / resolution.y) - 0.5 );
texColor.rgb = mix(texColor.rgb, texColor.rgb * smoothstep(RADIUS, RADIUS - 0.05, length(position)), 1.0); // здесь смешиваем цвет текстуры и интерполированное значение
gl_FragColor = texColor * vColor;
};

Самое интересное происходит в smoothstep(RADIUS, RADIUS - 0.05, length(position))
Насколько я понял, то это записана следующая функция:


Если просто круг нужен, то достаточно сделать так

gl_FragColor = smoothstep(RADIUS, RADIUS - 0.05, length(position)) * vColor

Всё это в уроке описано: и почему надо координаты поправить и как smoothstep работает. В коде для LibGdx перерасчета координат нет.

P.S. Спасибо за ссыль на мануал. Нравится как мужик пишет, потому хоть немного с шейдерами разобрался :D

ПрограммированиеФорумГрафика

Тема в архиве.